Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/startup')
-rw-r--r--release/scripts/startup/bl_operators/presets.py37
-rw-r--r--release/scripts/startup/bl_ui/__init__.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_gpencil.py402
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py445
-rw-r--r--release/scripts/startup/bl_ui/properties_data_shaderfx.py134
-rw-r--r--release/scripts/startup/bl_ui/properties_grease_pencil_common.py785
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_material_gpencil.py322
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py35
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py45
-rw-r--r--release/scripts/startup/bl_ui/space_image.py55
-rw-r--r--release/scripts/startup/bl_ui/space_node.py56
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py10
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py564
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py11
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py11
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py324
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py415
18 files changed, 2855 insertions, 806 deletions
diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py
index fe09fada297..0fe45f8fee3 100644
--- a/release/scripts/startup/bl_operators/presets.py
+++ b/release/scripts/startup/bl_operators/presets.py
@@ -670,6 +670,42 @@ class AddPresetUnitsLength(AddPresetBase, Operator):
preset_subdir = "units_length"
+class AddPresetGpencilBrush(AddPresetBase, Operator):
+ """Add or remove grease pencil brush preset"""
+ bl_idname = "scene.gpencil_brush_preset_add"
+ bl_label = "Add Grease Pencil Brush Preset"
+ preset_menu = "VIEW3D_PT_gpencil_brush_presets"
+
+ preset_defines = [
+ "brush = bpy.context.active_gpencil_brush",
+ "settings = brush.gpencil_settings"
+ ]
+
+ preset_values = [
+ "settings.input_samples",
+ "settings.active_smooth_factor",
+ "settings.angle",
+ "settings.angle_factor",
+ "settings.use_stabilizer",
+ "brush.smooth_stroke_radius",
+ "brush.smooth_stroke_factor",
+ "settings.pen_smooth_factor",
+ "settings.pen_smooth_steps",
+ "settings.pen_thick_smooth_factor",
+ "settings.pen_thick_smooth_steps",
+ "settings.pen_subdivision_steps",
+ "settings.random_subdiv",
+ "settings.enable_random",
+ "settings.random_pressure",
+ "settings.random_strength",
+ "settings.uv_random",
+ "settings.pen_jitter",
+ "settings.use_jitter_pressure",
+ ]
+
+ preset_subdir = "gpencil_brush"
+
+
classes = (
AddPresetCamera,
AddPresetCloth,
@@ -686,6 +722,7 @@ classes = (
AddPresetTrackingSettings,
AddPresetTrackingTrackColor,
AddPresetUnitsLength,
+ AddPresetGpencilBrush,
ExecutePreset,
WM_MT_operator_presets,
)
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 51ba45cdcd7..89aed37f055 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -34,16 +34,19 @@ _modules = [
"properties_data_camera",
"properties_data_curve",
"properties_data_empty",
+ "properties_data_gpencil",
"properties_data_light",
"properties_data_lattice",
"properties_data_mesh",
"properties_data_metaball",
"properties_data_modifier",
+ "properties_data_shaderfx",
"properties_data_lightprobe",
"properties_data_speaker",
"properties_data_workspace",
"properties_mask_common",
"properties_material",
+ "properties_material_gpencil",
"properties_object",
"properties_paint_common",
"properties_grease_pencil_common",
diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py
new file mode 100644
index 00000000000..14407afa8f2
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py
@@ -0,0 +1,402 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Menu, Panel, UIList
+from rna_prop_ui import PropertyPanel
+from .properties_grease_pencil_common import (
+ GreasePencilDataPanel,
+ GreasePencilOnionPanel,
+ )
+
+###############################
+# Base-Classes (for shared stuff - e.g. poll, attributes, etc.)
+
+class DataButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ return context.object and context.object.type == 'GPENCIL'
+
+
+class LayerDataButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+
+ @classmethod
+ def poll(cls, context):
+ return (context.object and
+ context.object.type == 'GPENCIL' and
+ context.active_gpencil_layer)
+
+
+###############################
+# GP Object Properties Panels and Helper Classes
+
+class DATA_PT_gpencil(DataButtonsPanel, Panel):
+ bl_label = ""
+ bl_options = {'HIDE_HEADER'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ # Grease Pencil data selector
+ gpd_owner = context.gpencil_data_owner
+ gpd = context.gpencil_data
+
+ layout.template_ID(gpd_owner, "data")
+
+
+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
+ gpd = context.gpencil_data
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ if gpl.lock:
+ layout.active = False
+
+ row = layout.row(align=True)
+ if gpl.is_parented:
+ icon = 'BONE_DATA'
+ else:
+ icon = 'BLANK1'
+
+ row.label(text="", icon=icon)
+ row.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)
+ row.prop(gpl, "unlock_color", text="", emboss=False)
+ if gpl.use_onion_skinning is False:
+ icon = 'GHOST_DISABLED'
+ else:
+ icon = 'GHOST_ENABLED'
+ subrow = row.row(align=True)
+ subrow.prop(gpl, "use_onion_skinning", text="", icon=icon, emboss=False)
+ subrow.active = gpd.use_onion_skinning
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class GPENCIL_MT_layer_specials(Menu):
+ bl_label = "Layer"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("gpencil.layer_duplicate", icon='COPY_ID') # XXX: needs a dedicated icon
+
+ layout.separator()
+
+ layout.operator("gpencil.reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
+ layout.operator("gpencil.hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
+
+ layout.separator()
+
+ layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All")
+ layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="UnLock All")
+
+ layout.separator()
+
+ layout.operator("gpencil.layer_merge", icon='NLA', text="Merge Down")
+
+
+class DATA_PT_gpencil_datapanel(Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Layers"
+
+ @classmethod
+ def poll(cls, context):
+ if context.gpencil_data is None:
+ return False
+
+ ob = context.object
+ if ob is not None and ob.type == 'GPENCIL':
+ return True
+
+ return False
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ #layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ gpd = context.gpencil_data
+
+ # Grease Pencil data...
+ if (gpd is None) or (not gpd.layers):
+ layout.operator("gpencil.layer_add", text="New Layer")
+ else:
+ 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.menu("GPENCIL_MT_layer_specials", icon='DOWNARROW_HLT', text="")
+
+ 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'
+
+ col.separator()
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
+ sub.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
+
+ row = layout.row(align=True)
+ if gpl:
+ row.prop(gpl, "opacity", text="Opacity", slider=True)
+
+
+class DATA_PT_gpencil_layer_optionpanel(LayerDataButtonsPanel, Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Adjustments"
+ bl_parent_id = 'DATA_PT_gpencil_datapanel'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ gpl = context.active_gpencil_layer
+ 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", slider=True)
+
+ # Offsets - Thickness
+ col = layout.row(align=True)
+ col.prop(gpl, "line_change", text="Stroke Thickness")
+
+
+class DATA_PT_gpencil_parentpanel(LayerDataButtonsPanel, Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Relations"
+ bl_parent_id = 'DATA_PT_gpencil_datapanel'
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ gpl = context.active_gpencil_layer
+ col = layout.column(align=True)
+ col.active = not gpl.lock
+ col.prop(gpl, "parent", text="Parent")
+ col.prop(gpl, "parent_type", text="Parent 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 DATA_PT_gpencil_onionpanel(Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Onion Skinning"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return bool(context.active_gpencil_layer)
+
+ @staticmethod
+ def draw_header(self, context):
+ self.layout.prop(context.gpencil_data, "use_onion_skinning", text="")
+
+ def draw(self, context):
+ gpd = context.gpencil_data
+
+ layout = self.layout
+ layout.use_property_split = True
+ layout.enabled = gpd.use_onion_skinning
+
+ GreasePencilOnionPanel.draw_settings(layout, gpd)
+
+
+class GPENCIL_MT_gpencil_vertex_group(Menu):
+ bl_label = "GP Vertex Groups"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'EXEC_AREA'
+ layout.operator("object.vertex_group_add")
+
+ ob = context.active_object
+ if ob.vertex_groups.active:
+ layout.separator()
+
+ layout.operator("gpencil.vertex_group_assign", text="Assign to Active Group")
+ layout.operator("gpencil.vertex_group_remove_from", text="Remove from Active Group")
+
+ layout.separator()
+ layout.operator_menu_enum("object.vertex_group_set_active", "group", text="Set Active Group")
+ layout.operator("object.vertex_group_remove", text="Remove Active Group").all = False
+ layout.operator("object.vertex_group_remove", text="Remove All Groups").all = True
+
+ layout.separator()
+ layout.operator("gpencil.vertex_group_select", text="Select Points")
+ layout.operator("gpencil.vertex_group_deselect", text="Deselect Points")
+
+
+class GPENCIL_UL_vgroups(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ vgroup = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.prop(vgroup, "name", text="", emboss=False, icon_value=icon)
+ # icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
+ # layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class DATA_PT_gpencil_vertexpanel(DataButtonsPanel, Panel):
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "data"
+ bl_label = "Vertex Groups"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+ group = ob.vertex_groups.active
+
+ rows = 2
+ if group:
+ rows = 4
+
+ row = layout.row()
+ row.template_list("GPENCIL_UL_vgroups", "", ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
+
+ col = row.column(align=True)
+ col.operator("object.vertex_group_add", icon='ZOOMIN', text="")
+ col.operator("object.vertex_group_remove", icon='ZOOMOUT', text="").all = False
+
+ if ob.vertex_groups:
+ row = layout.row()
+
+ sub = row.row(align=True)
+ sub.operator("gpencil.vertex_group_assign", text="Assign")
+ sub.operator("gpencil.vertex_group_remove_from", text="Remove")
+
+ sub = row.row(align=True)
+ sub.operator("gpencil.vertex_group_select", text="Select")
+ sub.operator("gpencil.vertex_group_deselect", text="Deselect")
+
+ layout.prop(context.tool_settings, "vertex_group_weight", text="Weight")
+
+
+class DATA_PT_gpencil_display(DataButtonsPanel, Panel):
+ bl_label = "Viewport Display"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+
+ gpd = context.gpencil_data
+ gpl = context.active_gpencil_layer
+
+ layout.prop(gpd, "xray_mode", text="Depth Ordering")
+ layout.prop(gpd, "edit_line_color", text="Edit Line Color")
+ layout.prop(ob, "empty_draw_size", text="Marker Size")
+
+ col = layout.column(align=True)
+ col.prop(gpd, "show_constant_thickness")
+ sub = col.column()
+ sub.active = not gpd.show_constant_thickness
+ sub.prop(gpd, "pixfactor", text="Thickness Scale")
+
+ if gpl:
+ layout.prop(gpd, "show_stroke_direction", text="Show Stroke Directions")
+
+
+class DATA_PT_custom_props_gpencil(DataButtonsPanel, PropertyPanel, Panel):
+ _context_path = "object.data"
+ _property_type = bpy.types.GreasePencil
+
+###############################
+
+classes = (
+ DATA_PT_gpencil,
+ DATA_PT_gpencil_datapanel,
+ DATA_PT_gpencil_onionpanel,
+ DATA_PT_gpencil_layer_optionpanel,
+ DATA_PT_gpencil_parentpanel,
+ DATA_PT_gpencil_vertexpanel,
+ DATA_PT_gpencil_display,
+ DATA_PT_custom_props_gpencil,
+
+ GPENCIL_UL_layer,
+ GPENCIL_UL_vgroups,
+
+ GPENCIL_MT_layer_specials,
+ GPENCIL_MT_gpencil_vertex_group,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 03ebea69d2b..2328925bbad 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -28,10 +28,14 @@ class ModifierButtonsPanel:
bl_context = "modifier"
bl_options = {'HIDE_HEADER'}
-
class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
bl_label = "Modifiers"
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return ob and ob.type != 'GPENCIL'
+
def draw(self, context):
layout = self.layout
@@ -1563,8 +1567,447 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
layout.operator("object.correctivesmooth_bind", text="Unbind" if is_bind else "Bind")
+class DATA_PT_gpencil_modifiers(ModifierButtonsPanel, Panel):
+ bl_label = "Modifiers"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return ob and ob.type == 'GPENCIL'
+
+ def draw(self, context):
+ layout = self.layout
+
+ ob = context.object
+
+ layout.operator_menu_enum("object.gpencil_modifier_add", "type")
+
+ for md in ob.grease_pencil_modifiers:
+ box = layout.template_greasepencil_modifier(md)
+ if box:
+ # match enum type to our functions, avoids a lookup table.
+ getattr(self, md.type)(box, ob, md)
+
+ # the mt.type enum is (ab)used for a lookup on function names
+ # ...to avoid lengthy if statements
+ # so each type must have a function here.
+
+ def GP_NOISE(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(md, "factor")
+ row.prop(md, "random", text="", icon="TIME", toggle=True)
+ row = col.row()
+ row.enabled = md.random
+ row.prop(md, "step")
+ col.prop(md, "full_stroke")
+ col.prop(md, "move_extreme")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row(align=True)
+ row.label("Affect:")
+ row = layout.row(align=True)
+ row.prop(md, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
+ row.prop(md, "affect_strength", text="Strength", icon='COLOR', toggle=True)
+ row.prop(md, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
+ row.prop(md, "affect_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
+
+ def GP_SMOOTH(self, layout, ob, md):
+ gpd = ob.data
+ row = layout.row(align=False)
+ row.prop(md, "factor")
+ row.prop(md, "step")
+
+ split = layout.split()
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col = split.column()
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row(align=True)
+ row.label("Affect:")
+ row = layout.row(align=True)
+ row.prop(md, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
+ row.prop(md, "affect_strength", text="Strength", icon='COLOR', toggle=True)
+ row.prop(md, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
+ row.prop(md, "affect_uv", text="UV", icon='MOD_UVPROJECT', toggle=True)
+
+ def GP_SUBDIV(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(md, "level")
+ row.prop(md, "simple", text="", icon="PARTICLE_POINT")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ def GP_SIMPLIFY(self, layout, ob, md):
+ gpd = ob.data
+
+ row = layout.row()
+ row.prop(md, "mode")
+
+ split = layout.split()
+
+ col = split.column()
+ col.label("Settings:")
+ row = col.row(align=True)
+ row.enabled = md.mode == 'FIXED'
+ row.prop(md, "step")
+
+ row = col.row(align=True)
+ row.enabled = not md.mode == 'FIXED'
+ row.prop(md, "factor")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ def GP_THICK(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ row = col.row(align=True)
+ row.prop(md, "thickness")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ col.prop(md, "normalize_thickness")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ if not md.normalize_thickness:
+ split = layout.split()
+ col = split.column()
+ col.prop(md, "use_custom_curve")
+
+ if md.use_custom_curve:
+ col.template_curve_mapping(md, "curve")
+
+ def GP_TINT(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "color")
+ col.prop(md, "factor")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row()
+ row.prop(md, "create_colors")
+
+ def GP_COLOR(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.label("Color:")
+ col.prop(md, "hue", text="H")
+ col.prop(md, "saturation", text="S")
+ col.prop(md, "value", text="V")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row()
+ row.prop(md, "create_colors")
+
+ def GP_OPACITY(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.label("Opacity:")
+ col.prop(md, "factor")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ def GP_INSTANCE(self, layout, ob, md):
+ gpd = ob.data
+
+ col = layout.column()
+ col.prop(md, "count")
+ col.prop(md, "use_make_objects")
+
+ split = layout.split()
+ col = split.column()
+ col.label("Offset:")
+ col.prop(md, "offset", text="")
+
+ col = split.column()
+ col.label("Shift:")
+ col.prop(md, "shift", text="")
+ row = col.row(align=True)
+ row.prop(md, "lock_axis", expand=True)
+
+ split = layout.split()
+ col = split.column()
+ col.label("Rotation:")
+ col.prop(md, "rotation", text="")
+ col.separator()
+ row = col.row(align=True)
+ row.prop(md, "random_rot", text="", icon="TIME", toggle=True)
+ row.prop(md, "rot_factor", text="")
+
+ col = split.column()
+ col.label("Scale:")
+ col.prop(md, "scale", text="")
+ col.separator()
+ row = col.row(align=True)
+ row.prop(md, "random_scale", text="", icon="TIME", toggle=True)
+ row.prop(md, "scale_factor", text="")
+
+ split = layout.split()
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ def GP_BUILD(self, layout, ob, md):
+ gpd = ob.data
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "mode")
+ if md.mode == 'CONCURRENT':
+ col.prop(md, "concurrent_time_alignment")
+ else:
+ col.separator() # For spacing
+ col.separator()
+ col.separator()
+
+ col.prop(md, "transition")
+ sub = col.column(align=True)
+ sub.prop(md, "start_delay")
+ sub.prop(md, "length")
+
+ col = split.column(align=True)
+ col.prop(md, "use_restrict_frame_range")
+ sub = col.column(align=True)
+ sub.active = md.use_restrict_frame_range
+ sub.prop(md, "frame_start", text="Start")
+ sub.prop(md, "frame_end", text="End")
+ col.separator()
+
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ def GP_LATTICE(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Object:")
+ col.prop(md, "object", text="")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ layout.separator()
+ layout.prop(md, "strength", slider=True)
+
+ def GP_MIRROR(self, layout, ob, md):
+ gpd = ob.data
+
+ row = layout.row(align=True)
+ row.prop(md, "x_axis")
+ row.prop(md, "y_axis")
+ row.prop(md, "z_axis")
+
+ # GPXX: Not implemented yet
+ # layout.separator()
+ # layout.prop(md, "clip")
+
+ layout.label("Layer:")
+ row = layout.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ row = layout.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ layout.label(text="Object:")
+ layout.prop(md, "object", text="")
+
+
+ def GP_HOOK(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.label(text="Object:")
+ col.prop(md, "object", text="")
+ if md.object and md.object.type == 'ARMATURE':
+ col.label(text="Bone:")
+ col.prop_search(md, "subtarget", md.object.data, "bones", text="")
+
+ col = split.column()
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+ use_falloff = (md.falloff_type != 'NONE')
+ split = layout.split()
+
+ layout.separator()
+
+ row = layout.row(align=True)
+ if use_falloff:
+ row.prop(md, "falloff_radius")
+ row.prop(md, "strength", slider=True)
+ layout.prop(md, "falloff_type")
+
+ col = layout.column()
+ if use_falloff:
+ if md.falloff_type == 'CURVE':
+ col.template_curve_mapping(md, "falloff_curve")
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "use_falloff_uniform")
+
+
+ def GP_OFFSET(self, layout, ob, md):
+ gpd = ob.data
+ split = layout.split()
+
+ col = split.column()
+ col.prop(md, "location")
+ col.prop(md, "scale")
+
+ col = split.column()
+ col.prop(md, "rotation")
+
+
+ col.label("Layer:")
+ row = col.row(align=True)
+ row.prop_search(md, "layer", gpd, "layers", text="", icon='GREASEPENCIL')
+ row.prop(md, "invert_layers", text="", icon="ARROW_LEFTRIGHT")
+
+ col.label("Vertex Group:")
+ row = col.row(align=True)
+ row.prop_search(md, "vertex_group", ob, "vertex_groups", text="")
+ row.prop(md, "invert_vertex", text="", icon="ARROW_LEFTRIGHT")
+
+ row = col.row(align=True)
+ row.prop(md, "pass_index", text="Pass")
+ row.prop(md, "invert_pass", text="", icon="ARROW_LEFTRIGHT")
+
+
classes = (
DATA_PT_modifiers,
+ DATA_PT_gpencil_modifiers,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_data_shaderfx.py b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
new file mode 100644
index 00000000000..5010f56d234
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_data_shaderfx.py
@@ -0,0 +1,134 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Panel
+from bpy.app.translations import pgettext_iface as iface_
+
+
+class ShaderFxButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "shaderfx"
+ bl_options = {'HIDE_HEADER'}
+
+class DATA_PT_shader_fx(ShaderFxButtonsPanel, Panel):
+ bl_label = "Effects"
+
+ @classmethod
+ def poll(cls, context):
+ return True
+ ob = context.object
+ return ob and ob.type == 'GPENCIL'
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ob = context.object
+
+ layout.operator_menu_enum("object.shaderfx_add", "type")
+
+ for fx in ob.shader_effects:
+ box = layout.template_shaderfx(fx)
+ if box:
+ # match enum type to our functions, avoids a lookup table.
+ getattr(self, fx.type)(box, fx)
+
+ # the mt.type enum is (ab)used for a lookup on function names
+ # ...to avoid lengthy if statements
+ # so each type must have a function here.
+
+ def FX_BLUR(self, layout, fx):
+
+ layout.prop(fx, "factor", text="Factor")
+ layout.prop(fx, "samples", text="Samples")
+
+ layout.separator()
+ layout.prop(fx, "use_dof_mode")
+ if fx.use_dof_mode:
+ layout.prop(fx, "coc")
+
+ def FX_COLORIZE(self, layout, fx):
+ layout.prop(fx, "mode", text="Mode")
+
+ if fx.mode == 'BITONE':
+ layout.prop(fx, "low_color", text="Low Color")
+ if fx.mode == 'CUSTOM':
+ layout.prop(fx, "low_color", text="Color")
+
+ if fx.mode == 'BITONE':
+ layout.prop(fx, "high_color", text="High Color")
+
+ if fx.mode in {'BITONE', 'CUSTOM', 'TRANSPARENT'}:
+ layout.prop(fx, "factor")
+
+ def FX_WAVE(self, layout,fx):
+ layout.prop(fx, "orientation", expand=True)
+
+ layout.separator()
+ layout.prop(fx, "amplitude")
+ layout.prop(fx, "period")
+ layout.prop(fx, "phase")
+
+ def FX_PIXEL(self, layout, fx):
+ layout.prop(fx, "size", text="Size")
+
+ layout.prop(fx, "use_lines", text="Display Lines")
+
+ col = layout.column()
+ col.enabled = fx.use_lines
+ col.prop(fx, "color")
+
+ def FX_RIM(self, layout, fx):
+ layout.prop(fx, "offset", text="Offset")
+
+ layout.prop(fx, "rim_color")
+ layout.prop(fx, "mask_color")
+ layout.prop(fx, "mode")
+ layout.prop(fx, "blur")
+ layout.prop(fx, "samples")
+
+ def FX_SWIRL(self, layout, fx):
+ layout.prop(fx, "object", text="Object")
+
+ layout.prop(fx, "radius")
+ layout.prop(fx, "angle")
+
+ layout.prop(fx, "transparent")
+
+ def FX_FLIP(self, layout, fx):
+ layout.prop(fx, "flip_horizontal")
+ layout.prop(fx, "flip_vertical")
+
+ def FX_LIGHT(self, layout, fx):
+ layout.prop(fx, "object", text="Object")
+
+ layout.prop(fx, "energy")
+ layout.prop(fx, "ambient")
+
+
+classes = (
+ DATA_PT_shader_fx,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
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 55b798d103a..252f87d369f 100644
--- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
+++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py
@@ -18,45 +18,30 @@
# <pep8 compliant>
-
+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 = "gpencil_stroke_placement_view3d"
+ propname = "annotation_stroke_placement_view3d"
elif context.space_data.type == 'SEQUENCE_EDITOR':
- propname = "gpencil_stroke_placement_sequencer_preview"
+ propname = "annotation_stroke_placement_sequencer_preview"
elif context.space_data.type == 'IMAGE_EDITOR':
- propname = "gpencil_stroke_placement_image_editor"
+ propname = "annotation_stroke_placement_image_editor"
else:
- propname = "gpencil_stroke_placement_view2d"
+ propname = "annotation_stroke_placement_view2d"
ts = context.tool_settings
col = layout.column(align=True)
- col.label(text="Stroke Placement:")
-
- row = col.row(align=True)
- row.prop_enum(ts, propname, 'VIEW')
- row.prop_enum(ts, propname, 'CURSOR')
-
- if context.space_data.type == 'VIEW_3D':
+ if context.space_data.type != 'VIEW_3D':
+ col.label(text="Stroke Placement:")
row = col.row(align=True)
- row.prop_enum(ts, propname, 'SURFACE')
- row.prop_enum(ts, propname, 'STROKE')
-
- row = col.row(align=False)
- row.active = getattr(ts, propname) in {'SURFACE', 'STROKE'}
- row.prop(ts, "use_gpencil_stroke_endpoints")
-
- if context.scene.tool_settings.gpencil_stroke_placement_view3d == 'CURSOR':
- row = col.row(align=True)
- row.label("Lock axis:")
- row = col.row(align=True)
- row.prop(ts.gpencil_sculpt, "lockaxis", expand=True)
+ row.prop_enum(ts, propname, 'VIEW')
+ row.prop_enum(ts, propname, 'CURSOR', text="Cursor")
def gpencil_active_brush_settings_simple(context, layout):
@@ -73,7 +58,7 @@ def gpencil_active_brush_settings_simple(context, layout):
row.operator_menu_enum("gpencil.brush_change", "brush", text="", icon='BRUSH_DATA')
row.prop(brush, "name", text="")
- col.prop(brush, "line_width", slider=True)
+ 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)
@@ -90,6 +75,7 @@ def gpencil_active_brush_settings_simple(context, layout):
row.prop(brush, "angle_factor", text="Factor", slider=True)
+# XXX: To be replaced with active tools
class GreasePencilDrawingToolsPanel:
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
@@ -99,8 +85,7 @@ class GreasePencilDrawingToolsPanel:
@classmethod
def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
+ return True
@staticmethod
def draw(self, context):
@@ -113,12 +98,12 @@ class GreasePencilDrawingToolsPanel:
col.label(text="Draw:")
row = col.row(align=True)
- row.operator("gpencil.draw", icon='GREASEPENCIL', text="Draw").mode = 'DRAW'
- row.operator("gpencil.draw", icon='FORCE_CURVE', text="Erase").mode = 'ERASER' # XXX: Needs a dedicated icon
+ row.operator("gpencil.annotate", icon='GREASEPENCIL', text="Draw").mode = 'DRAW'
+ row.operator("gpencil.annotate", icon='FORCE_CURVE', text="Erase").mode = 'ERASER' # XXX: Needs a dedicated icon
row = col.row(align=True)
- row.operator("gpencil.draw", icon='LINE_DATA', text="Line").mode = 'DRAW_STRAIGHT'
- row.operator("gpencil.draw", icon='MESH_DATA', text="Poly").mode = 'DRAW_POLY'
+ 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()
@@ -126,15 +111,15 @@ class GreasePencilDrawingToolsPanel:
sub.operator("gpencil.blank_frame_add", icon='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_additive_drawing", 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")
+ #sub = col.column(align=True)
+ #sub.prop(context.tool_settings, "use_gpencil_additive_drawing", 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 in {'VIEW_3D', 'CLIP_EDITOR'}:
+ if context.space_data.type in {'CLIP_EDITOR'}:
col.separator()
col.label("Data Source:")
row = col.row(align=True)
@@ -143,8 +128,8 @@ class GreasePencilDrawingToolsPanel:
elif is_clip_editor:
row.prop(context.space_data, "grease_pencil_source", expand=True)
- col.separator()
- col.separator()
+ #col.separator()
+ #col.separator()
gpencil_stroke_placement_settings(context, col)
@@ -157,28 +142,16 @@ class GreasePencilDrawingToolsPanel:
col = layout.column(align=True)
col.prop(gpd, "use_stroke_edit_mode", text="Enable Editing", icon='EDIT', toggle=True)
- if is_3d_view:
- col.separator()
- col.separator()
-
- col.label(text="Tools:")
- col.operator_menu_enum("gpencil.convert", text="Convert to Geometry...", property="type")
- col.operator("view3d.ruler")
-
class GreasePencilStrokeEditPanel:
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
bl_label = "Edit Strokes"
- bl_category = "Grease Pencil"
+ bl_category = "Tools"
bl_region_type = 'TOOLS'
- bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
-
if context.gpencil_data is None:
return False
@@ -204,7 +177,7 @@ class GreasePencilStrokeEditPanel:
col.operator("gpencil.select_linked")
col.operator("gpencil.select_more")
col.operator("gpencil.select_less")
- col.operator("gpencil.palettecolor_select")
+ col.operator("gpencil.select_alternate")
layout.label(text="Edit:")
row = layout.row(align=True)
@@ -228,258 +201,124 @@ class GreasePencilStrokeEditPanel:
layout.separator()
- col = layout.column(align=True)
- col.operator("transform.bend", text="Bend")
- col.operator("transform.mirror", text="Mirror")
- col.operator("transform.shear", text="Shear")
- col.operator("transform.tosphere", text="To Sphere")
-
layout.separator()
col = layout.column(align=True)
col.operator_menu_enum("gpencil.stroke_arrange", text="Arrange Strokes...", property="direction")
col.operator("gpencil.stroke_change_color", text="Move to Color")
- if is_3d_view:
- layout.separator()
-
layout.separator()
col = layout.column(align=True)
col.operator("gpencil.stroke_subdivide", text="Subdivide")
- col.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
- col.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
- col.operator("gpencil.stroke_flip", text="Flip Direction")
-
- gpd = context.gpencil_data
- if gpd:
- col.prop(gpd, "show_stroke_direction", text="Show Directions")
-
- if is_3d_view:
- layout.separator()
- layout.operator_menu_enum("gpencil.reproject", text="Reproject Strokes...", property="type")
-
-
-class GreasePencilInterpolatePanel:
- bl_space_type = 'VIEW_3D'
- bl_label = "Interpolate"
- bl_category = "Grease Pencil"
- bl_region_type = 'TOOLS'
- bl_options = {'DEFAULT_CLOSED'}
-
- @classmethod
- def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
-
- if context.gpencil_data is None:
- return False
- elif context.space_data.type != 'VIEW_3D':
- return False
-
- gpd = context.gpencil_data
- return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
-
- @staticmethod
- def draw(self, context):
- layout = self.layout
- settings = context.tool_settings.gpencil_interpolate
-
- col = layout.column(align=True)
- col.operator("gpencil.interpolate", text="Interpolate")
- col.operator("gpencil.interpolate_sequence", text="Sequence")
- col.operator("gpencil.interpolate_reverse", text="Remove Breakdowns")
-
- col = layout.column(align=True)
- col.label(text="Options:")
- col.prop(settings, "interpolate_all_layers")
- col.prop(settings, "interpolate_selected_only")
-
- col = layout.column(align=True)
- col.label(text="Sequence Options:")
- col.prop(settings, "type")
- if settings.type == 'CUSTOM':
- box = layout.box()
- # TODO: Options for loading/saving curve presets?
- box.template_curve_mapping(settings, "interpolation_curve", brush=True)
- elif settings.type != 'LINEAR':
- col.prop(settings, "easing")
-
- if settings.type == 'BACK':
- layout.prop(settings, "back")
- elif setting.type == 'ELASTIC':
- sub = layout.column(align=True)
- sub.prop(settings, "amplitude")
- sub.prop(settings, "period")
-
-
-class GreasePencilBrushPanel:
- # subclass must set
- # bl_space_type = 'IMAGE_EDITOR'
- bl_label = "Drawing Brushes"
- bl_category = "Grease Pencil"
- bl_region_type = 'TOOLS'
-
- @classmethod
- def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
+ row = col.row(align=True)
+ row.operator("gpencil.stroke_simplify_fixed", text="Simplify")
+ row.operator("gpencil.stroke_simplify", text="Adaptative")
- @staticmethod
- def draw(self, context):
- layout = self.layout
+ col.separator()
- row = layout.row()
- col = row.column()
- ts = context.scene.tool_settings
- if len(ts.gpencil_brushes) >= 2:
- brows = 3
- else:
- brows = 2
- col.template_list("GPENCIL_UL_brush", "", ts, "gpencil_brushes", ts.gpencil_brushes, "active_index", rows=brows)
+ row = col.row(align=True)
+ row.operator("gpencil.stroke_join", text="Join").type = 'JOIN'
+ row.operator("gpencil.stroke_join", text="& Copy").type = 'JOINCOPY'
- col = row.column()
+ col.operator("gpencil.stroke_flip", text="Flip Direction")
- sub = col.column(align=True)
- sub.operator("gpencil.brush_add", icon='ZOOMIN', text="")
- sub.operator("gpencil.brush_remove", icon='ZOOMOUT', text="")
- sub.menu("GPENCIL_MT_brush_specials", icon='DOWNARROW_HLT', text="")
- brush = context.active_gpencil_brush
- if brush:
- if len(ts.gpencil_brushes) > 1:
- col.separator()
- sub = col.column(align=True)
- sub.operator("gpencil.brush_move", icon='TRIA_UP', text="").type = 'UP'
- sub.operator("gpencil.brush_move", icon='TRIA_DOWN', text="").type = 'DOWN'
+ if is_3d_view:
+ layout.separator()
- # Brush details
- if brush is not None:
- row = layout.row()
- row.prop(brush, "line_width")
- row = layout.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 = layout.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 = layout.row(align=True)
- row.prop(brush, "random_press", slider=True)
+ col = layout.column(align=True)
+ col.operator_menu_enum("gpencil.stroke_separate", text="Separate...", property="mode")
+ col.operator("gpencil.stroke_split", text="Split")
- row = layout.row(align=True)
- row.prop(brush, "jitter", slider=True)
- row.prop(brush, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
- row = layout.row()
- row.prop(brush, "angle", slider=True)
- row.prop(brush, "angle_factor", text="Factor", slider=True)
-
- box = layout.box()
- col = box.column(align=True)
- col.label(text="Stroke Quality:")
- col.prop(brush, "pen_smooth_factor")
- col.prop(brush, "pen_smooth_steps")
- col.separator()
- row = col.row(align=False)
- row.prop(brush, "pen_subdivision_steps")
- row.prop(brush, "random_subdiv", text="Randomness", slider=True)
+ col = layout.column(align=True)
+ col.label(text="Cleanup:")
+ col.operator_menu_enum("gpencil.reproject", text="Reproject Strokes...", property="type")
+ col.operator_menu_enum("gpencil.frame_clean_fill", text="Clean Boundary Strokes...", property="mode")
class GreasePencilStrokeSculptPanel:
# subclass must set
# bl_space_type = 'IMAGE_EDITOR'
bl_label = "Sculpt Strokes"
- bl_category = "Grease Pencil"
- bl_region_type = 'TOOLS'
-
- @classmethod
- def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
-
- if context.gpencil_data is None:
- return False
-
- gpd = context.gpencil_data
- return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
+ bl_category = "Tools"
@staticmethod
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.tool
brush = settings.brush
- layout.column().prop(settings, "tool")
+ layout.template_icon_view(settings, "tool", show_labels=True)
- col = layout.column()
- col.prop(brush, "size", slider=True)
- row = col.row(align=True)
+ layout.prop(brush, "size", slider=True)
+ row = layout.row(align=True)
row.prop(brush, "strength", slider=True)
row.prop(brush, "use_pressure_strength", text="")
- col.prop(brush, "use_falloff")
- if tool in {'SMOOTH', 'RANDOMIZE'}:
- row = layout.row(align=True)
- row.prop(settings, "affect_position", text="Position", icon='MESH_DATA', toggle=True)
- row.prop(settings, "affect_strength", text="Strength", icon='COLOR', toggle=True)
- row.prop(settings, "affect_thickness", text="Thickness", icon='LINE_DATA', toggle=True)
- layout.separator()
+ layout.prop(brush, "use_falloff")
- if tool == 'THICKNESS':
- layout.row().prop(brush, "direction", expand=True)
- elif tool == 'PINCH':
- row = layout.row(align=True)
- row.prop_enum(brush, "direction", 'ADD', text="Pinch")
- row.prop_enum(brush, "direction", 'SUBTRACT', text="Inflate")
- elif settings.tool == 'TWIST':
- row = layout.row(align=True)
- row.prop_enum(brush, "direction", 'SUBTRACT', text="CW")
- row.prop_enum(brush, "direction", 'ADD', text="CCW")
+ if tool in {'SMOOTH', 'RANDOMIZE'}:
+ layout.prop(settings, "affect_position", text="Affect Position")
+ layout.prop(settings, "affect_strength", text="Affect Strength")
+ layout.prop(settings, "affect_thickness", text="Affect Thickness")
- row = layout.row(align=True)
- row.prop(settings, "use_select_mask")
- row = layout.row(align=True)
- row.prop(settings, "selection_alpha", slider=True)
+ if tool == 'SMOOTH':
+ layout.prop(brush, "affect_pressure")
- if tool == 'SMOOTH':
- layout.prop(brush, "affect_pressure")
+ layout.prop(settings, "affect_uv", text="Affect UV")
+ if tool in {'THICKNESS', 'PINCH', 'TWIST'}:
+ layout.prop(brush, "direction", expand=True)
-class GreasePencilBrushCurvesPanel:
- # subclass must set
- # bl_space_type = 'IMAGE_EDITOR'
- bl_label = "Brush Curves"
- bl_category = "Grease Pencil"
- bl_region_type = 'TOOLS'
+
+# GP Object Tool Settings
+class GreasePencilAppearancePanel:
+ bl_label = "Brush Appearance"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
-
- if context.active_gpencil_brush is None:
- return False
-
- brush = context.active_gpencil_brush
- return bool(brush)
+ ob = context.active_object
+ return ob and ob.type == 'GPENCIL'
@staticmethod
def draw(self, context):
layout = self.layout
- brush = context.active_gpencil_brush
- # Brush
- layout.label("Sensitivity")
- box = layout.box()
- box.template_curve_mapping(brush, "curve_sensitivity", brush=True)
+ layout.use_property_split = True
+ layout.use_property_decorate = False
- layout.label("Strength")
- box = layout.box()
- box.template_curve_mapping(brush, "curve_strength", brush=True)
+ ob = context.active_object
- layout.label("Jitter")
- box = layout.box()
- box.template_curve_mapping(brush, "curve_jitter", brush=True)
+ if ob.mode == 'GPENCIL_PAINT':
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+
+ layout.prop(gp_settings, "gpencil_brush_type", text="Brush Type")
+
+ sub = layout.column(align=True)
+ sub.enabled = not brush.use_custom_icon
+ sub.prop(gp_settings, "gp_icon", text="Icon")
+
+ layout.prop(brush, "use_custom_icon")
+ sub = layout.column()
+ sub.active = brush.use_custom_icon
+ sub.prop(brush, "icon_filepath", text="")
+
+ layout.prop(gp_settings, "use_cursor", text="Show Brush")
+
+ if gp_settings.gpencil_brush_type == 'FILL':
+ layout.prop(brush, "cursor_color_add", text="Color")
+
+ elif ob.mode in ('GPENCIL_SCULPT', 'GPENCIL_WEIGHT'):
+ settings = context.tool_settings.gpencil_sculpt
+ brush = settings.brush
+
+ col = layout.column(align=True)
+ col.prop(brush, "use_cursor", text="Show Brush")
+ col.row().prop(brush, "cursor_color_add", text="Add")
+ col.row().prop(brush, "cursor_color_sub", text="Subtract")
###############################
@@ -539,6 +378,7 @@ class GPENCIL_MT_pie_tool_palette(Menu):
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')
+ col.operator("gpencil.select_alternate", text="Alternate Select", icon='BORDER_LASSO')
# SW - Edit Tools
col = pie.column()
@@ -566,7 +406,7 @@ class GPENCIL_MT_pie_settings_palette(Menu):
pie = layout.menu_pie()
gpd = context.gpencil_data
gpl = context.active_gpencil_layer
- palcolor = context.active_gpencil_palettecolor
+ palcolor = None #context.active_gpencil_palettecolor
brush = context.active_gpencil_brush
is_editmode = bool(gpd and gpd.use_stroke_edit_mode and context.editable_gpencil_strokes)
@@ -737,6 +577,16 @@ class GPENCIL_MT_snap(Menu):
layout.operator("view3d.snap_cursor_to_grid", text="Cursor to Grid")
+class GPENCIL_MT_separate(Menu):
+ bl_label = "Separate"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator("gpencil.stroke_separate", text="Selected Points").mode = 'POINT'
+ layout.operator("gpencil.stroke_separate", text="Selected Strokes").mode = 'STROKE'
+ layout.operator("gpencil.stroke_separate", text="Active Layer").mode = 'LAYER'
+
+
class GPENCIL_MT_gpencil_edit_specials(Menu):
bl_label = "GPencil Specials"
@@ -747,6 +597,14 @@ class GPENCIL_MT_gpencil_edit_specials(Menu):
layout.operator_context = 'INVOKE_REGION_WIN'
layout.operator("gpencil.stroke_subdivide", text="Subdivide")
+ layout.operator("gpencil.stroke_simplify_fixed", text="Simplify")
+ layout.operator("gpencil.stroke_simplify", text="Simplify Adaptative")
+
+ layout.separator()
+ layout.menu("GPENCIL_MT_separate", text="Separate")
+
+ layout.separator()
+ layout.operator("gpencil.stroke_split", text="Split")
layout.separator()
@@ -754,167 +612,129 @@ class GPENCIL_MT_gpencil_edit_specials(Menu):
layout.operator("gpencil.stroke_join", text="Join & Copy").type = 'JOINCOPY'
layout.operator("gpencil.stroke_flip", text="Flip Direction")
+ layout.separator()
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame")
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame All Layers").mode = 'ALL'
+
if is_3d_view:
layout.separator()
layout.operator("gpencil.reproject")
-###############################
-
-
-class GPENCIL_UL_brush(UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- # assert(isinstance(item, bpy.types.GPencilBrush)
- brush = item
-
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- row = layout.row(align=True)
- row.prop(brush, "name", text="", emboss=False, icon='BRUSH_DATA')
- elif self.layout_type == 'GRID':
- layout.alignment = 'CENTER'
- layout.label(text="", icon_value=icon)
-
-
-class GPENCIL_UL_palettecolor(UIList):
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
- # assert(isinstance(item, bpy.types.PaletteColor)
- palcolor = item
-
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- if palcolor.lock:
- layout.active = False
-
- split = layout.split(percentage=0.25)
- row = split.row(align=True)
- row.enabled = not palcolor.lock
- row.prop(palcolor, "color", text="", emboss=palcolor.is_stroke_visible)
- row.prop(palcolor, "fill_color", text="", emboss=palcolor.is_fill_visible)
- split.prop(palcolor, "name", text="", emboss=False)
-
- row = layout.row(align=True)
- row.prop(palcolor, "lock", text="", emboss=False)
- row.prop(palcolor, "hide", text="", emboss=False)
- if palcolor.ghost is True:
- icon = 'GHOST_DISABLED'
- else:
- icon = 'GHOST_ENABLED'
- row.prop(palcolor, "ghost", text="", icon=icon, emboss=False)
-
- elif self.layout_type == 'GRID':
- layout.alignment = 'CENTER'
- layout.label(text="", icon_value=icon)
-
+class GPENCIL_MT_gpencil_sculpt_specials(Menu):
+ bl_label = "GPencil Specials"
-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
+ def draw(self, context):
+ layout = self.layout
+ is_3d_view = context.space_data.type == 'VIEW_3D'
- if self.layout_type in {'DEFAULT', 'COMPACT'}:
- if gpl.lock:
- layout.active = False
+ layout.operator_context = 'INVOKE_REGION_WIN'
- row = layout.row(align=True)
- if gpl.is_parented:
- icon = 'BONE_DATA'
- else:
- icon = 'BLANK1'
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame")
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame All Layers").mode = 'ALL'
- row.label(text="", icon=icon)
- row.prop(gpl, "info", text="", emboss=False)
+ layout.separator()
- row = layout.row(align=True)
- row.prop(gpl, "lock", text="", emboss=False)
- row.prop(gpl, "hide", text="", emboss=False)
- row.prop(gpl, "unlock_color", text="", emboss=False)
- elif self.layout_type == 'GRID':
- layout.alignment = 'CENTER'
- layout.label(text="", icon_value=icon)
+ layout.operator("gpencil.stroke_subdivide", text="Subdivide")
+ layout.operator("gpencil.stroke_simplify_fixed", text="Simplify")
+ layout.operator("gpencil.stroke_simplify", text="Simplify Adaptative")
-class GPENCIL_MT_layer_specials(Menu):
- bl_label = "Layer"
+class GPENCIL_MT_gpencil_draw_specials(Menu):
+ bl_label = "GPencil Draw Specials"
def draw(self, context):
layout = self.layout
+ is_3d_view = context.space_data.type == 'VIEW_3D'
- layout.operator("gpencil.layer_duplicate", icon='COPY_ID') # XXX: needs a dedicated icon
-
- layout.separator()
+ layout.operator_context = 'INVOKE_REGION_WIN'
- layout.operator("gpencil.reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
- layout.operator("gpencil.hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame")
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame All Layers").mode = 'ALL'
layout.separator()
+ layout.operator("gpencil.primitive", text="Line", icon='IPO_CONSTANT').type = 'LINE'
+ layout.operator("gpencil.primitive", text="Rectangle", icon='UV_FACESEL').type = 'BOX'
+ layout.operator("gpencil.primitive", text="Circle", icon='ANTIALIASED').type = 'CIRCLE'
- layout.operator("gpencil.lock_all", icon='LOCKED', text="Lock All")
- layout.operator("gpencil.unlock_all", icon='UNLOCKED', text="UnLock All")
-
+ # colors
layout.separator()
+ layout.operator("gpencil.colorpick", text="Colors", icon="GROUP_VCOL")
- layout.operator("gpencil.layer_merge", icon='NLA', text="Merge Down")
-
-class GPENCIL_MT_brush_specials(Menu):
- bl_label = "Layer"
+class GPENCIL_MT_gpencil_draw_delete(Menu):
+ bl_label = "GPencil Draw Delete"
def draw(self, context):
layout = self.layout
- layout.operator("gpencil.brush_copy", icon='PASTEDOWN', text="Copy Current Drawing Brush")
- layout.operator("gpencil.brush_presets_create", icon='HELP', text="Create a Set of Predefined Brushes")
-
+ is_3d_view = context.space_data.type == 'VIEW_3D'
-class GPENCIL_MT_palettecolor_specials(Menu):
- bl_label = "Layer"
+ layout.operator_context = 'INVOKE_REGION_WIN'
- def draw(self, context):
- layout = self.layout
+ layout.operator("gpencil.active_frames_delete_all", text="Delete Frame")
- layout.operator("gpencil.palettecolor_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
- layout.operator("gpencil.palettecolor_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
- layout.separator()
+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
+ gpd = context.gpencil_data
- layout.operator("gpencil.palettecolor_lock_all", icon='LOCKED', text="Lock All")
- layout.operator("gpencil.palettecolor_unlock_all", icon='UNLOCKED', text="UnLock All")
- layout.operator("gpencil.palettecolor_copy", icon='PASTEDOWN', text="Copy Color")
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ if gpl.lock:
+ layout.active = False
- layout.separator()
+ split = layout.split(percentage=0.2)
+ split.prop(gpl, "color", text="", emboss=True)
+ split.prop(gpl, "info", text="", emboss=False)
- layout.operator("gpencil.palettecolor_select", icon='COLOR', text="Select Strokes")
- layout.operator("gpencil.stroke_change_color", icon='MAN_TRANS', text="Move to Color")
+ row = layout.row(align=True)
+ # row.prop(gpl, "lock", text="", emboss=False)
+ row.prop(gpl, "hide", text="", emboss=False)
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
class GreasePencilDataPanel:
- # subclass must set
- # bl_space_type = 'IMAGE_EDITOR'
- bl_label = "Grease Pencil Layers"
+ bl_label = "Annotations"
bl_region_type = 'UI'
+ @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
+
@staticmethod
def draw_header(self, context):
- self.layout.prop(context.space_data, "show_grease_pencil", text="")
+ if context.space_data.type != 'VIEW_3D':
+ self.layout.prop(context.space_data, "show_annotation", text="")
@staticmethod
def draw(self, context):
layout = self.layout
+ #layout.use_property_split = True
+ layout.use_property_decorate = False
# 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.row().prop(context.tool_settings, "grease_pencil_source", expand=True)
- elif context.space_data.type == 'CLIP_EDITOR':
+ if context.space_data.type == 'CLIP_EDITOR':
layout.row().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 is None) or (not gpd.layers):
- layout.operator("gpencil.layer_add", text="New Layer")
+ layout.operator("gpencil.layer_add", text="New Note")
else:
self.draw_layers(context, layout, gpd)
@@ -926,7 +746,7 @@ class GreasePencilDataPanel:
layer_rows = 5
else:
layer_rows = 2
- col.template_list("GPENCIL_UL_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows)
+ col.template_list("GPENCIL_UL_annotation_layer", "", gpd, "layers", gpd.layers, "active_index", rows=layer_rows)
col = row.column()
@@ -936,8 +756,6 @@ class GreasePencilDataPanel:
gpl = context.active_gpencil_layer
if gpl:
- sub.menu("GPENCIL_MT_layer_specials", icon='DOWNARROW_HLT', text="")
-
if len(gpd.layers) > 1:
col.separator()
@@ -945,203 +763,70 @@ class GreasePencilDataPanel:
sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP'
sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN'
- col.separator()
-
- sub = col.column(align=True)
- sub.operator("gpencil.layer_isolate", icon='LOCKED', text="").affect_visibility = False
- sub.operator("gpencil.layer_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
-
if gpl:
- self.draw_layer(context, layout, gpl)
-
- def draw_layer(self, context, layout, gpl):
- row = layout.row(align=True)
- row.prop(gpl, "opacity", text="Opacity", slider=True)
-
- # Layer options
- split = layout.split(percentage=0.5)
- split.active = not gpl.lock
- split.prop(gpl, "show_x_ray")
- split.prop(gpl, "show_points")
-
- # Offsets + Parenting (where available)
- if context.space_data.type == 'VIEW_3D':
- split = layout.split(percentage=0.5)
- else:
- split = layout.column() # parenting is not available in 2D editors...
- split.active = not gpl.lock
-
- # Offsets - Color Tint
- col = split.column()
- subcol = col.column(align=True)
- subcol.label("Tint")
- subcol.enabled = not gpl.lock
- subcol.prop(gpl, "tint_color", text="")
- subcol.prop(gpl, "tint_factor", text="Factor", slider=True)
-
- # Offsets - Thickness
- row = col.row(align=True)
- row.prop(gpl, "line_change", text="Thickness Change", slider=True)
- row.operator("gpencil.stroke_apply_thickness", icon='STYLUS_PRESSURE', text="")
+ # layout.prop(gpl, "opacity", text="Opacity", slider=True)
+ # layout.prop(gpl, "thickness", text="Thickness")
+ #
+ # layout.separator()
- # Parenting
- if context.space_data.type == 'VIEW_3D':
- col = split.column(align=True)
- col.label(text="Parent:")
- col.prop(gpl, "parent", text="")
+ # Full-Row - Frame Locking (and Delete Frame)
+ row = layout.row(align=True)
+ row.active = not gpl.lock
- sub = col.column()
- sub.prop(gpl, "parent_type", text="")
- parent = gpl.parent
- if parent and gpl.parent_type == 'BONE' and parent.type == 'ARMATURE':
- sub.prop_search(gpl, "parent_bone", parent.data, "bones", text="")
+ 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')
- 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 = 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')
-
- layout.separator()
+class GreasePencilOnionPanel:
+ @staticmethod
+ def draw_settings(layout, gp):
+ col = layout.column()
- # Onion skinning
- col = layout.column(align=True)
- col.active = not gpl.lock
+ col.prop(gp, "onion_mode")
row = col.row()
- row.prop(gpl, "use_onion_skinning")
- sub = row.row(align=True)
- icon = 'RESTRICT_RENDER_OFF' if gpl.use_ghosts_always else 'RESTRICT_RENDER_ON'
- sub.prop(gpl, "use_ghosts_always", text="", icon=icon)
- sub.prop(gpl, "use_ghost_custom_colors", text="", icon='COLOR')
-
- split = col.split(percentage=0.5)
- split.active = gpl.use_onion_skinning
+ row.prop(gp, "onion_factor", text="Opacity", slider=True)
# - Before Frames
- sub = split.column(align=True)
+ sub = layout.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")
+ row.active = gp.use_ghost_custom_colors
+ row.prop(gp, "before_color", text="Color 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 GreasePencilPaletteColorPanel:
- # subclass must set
- bl_label = "Grease Pencil Colors"
- bl_region_type = 'UI'
-
- @classmethod
- def poll(cls, context):
- # XXX - disabled in 2.8 branch.
- return False
-
- if context.gpencil_data is None:
- return False
-
- gpd = context.gpencil_data
- return bool(gpd.layers.active)
-
- @staticmethod
- def draw(self, context):
- layout = self.layout
- palette = context.active_gpencil_palette
+ row.active = gp.onion_mode in ('ABSOLUTE', 'RELATIVE')
+ row.prop(gp, "ghost_before_range", text="Frames Before")
- if palette:
- row = layout.row(align=True)
- row.operator_context = 'EXEC_REGION_WIN'
- row.operator_menu_enum("gpencil.palette_change", "palette", text="", icon='COLOR')
- row.prop(palette, "name", text="")
- row.operator("gpencil.palette_add", icon='ZOOMIN', text="")
- row.operator("gpencil.palette_remove", icon='X', text="")
-
- # Palette colors
- row = layout.row()
- col = row.column()
- if len(palette.colors) >= 2:
- color_rows = 5
- else:
- color_rows = 2
- col.template_list("GPENCIL_UL_palettecolor", "", palette, "colors", palette.colors, "active_index",
- rows=color_rows)
-
- col = row.column()
+ # - After Frames
+ sub = layout.column(align=True)
+ row = sub.row(align=True)
+ row.active = gp.use_ghost_custom_colors
+ row.prop(gp, "after_color", text="Color After")
- sub = col.column(align=True)
- sub.operator("gpencil.palettecolor_add", icon='ZOOMIN', text="")
- sub.operator("gpencil.palettecolor_remove", icon='ZOOMOUT', text="")
+ row = sub.row(align=True)
+ row.active = gp.onion_mode in ('ABSOLUTE', 'RELATIVE')
+ row.prop(gp, "ghost_after_range", text="Frames After")
- palcol = context.active_gpencil_palettecolor
- if palcol:
- sub.menu("GPENCIL_MT_palettecolor_specials", icon='DOWNARROW_HLT', text="")
+ layout.prop(gp, "use_ghost_custom_colors", text="Use Custom Color")
+ layout.prop(gp, "use_ghosts_always", text="View In Render")
- if len(palette.colors) > 1:
- col.separator()
+ # - fade and loop
+ row = layout.row()
+ row.active = gp.use_onion_skinning
+ row.prop(gp, "use_onion_fade", text="Fade")
+ if hasattr(gp, "use_onion_loop"): # XXX
+ subrow = layout.row()
+ subrow.active = gp.onion_mode in ('RELATIVE', 'SELECTED')
+ subrow.prop(gp, "use_onion_loop", text="Loop")
- sub = col.column(align=True)
- sub.operator("gpencil.palettecolor_move", icon='TRIA_UP', text="").direction = 'UP'
- sub.operator("gpencil.palettecolor_move", icon='TRIA_DOWN', text="").direction = 'DOWN'
-
- row = layout.row()
- sub = row.row(align=True)
- sub.label(text="Isolate:") # based on active color only
- sub.operator("gpencil.palettecolor_isolate", icon='LOCKED', text="").affect_visibility = False
- sub.operator("gpencil.palettecolor_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
- sub = row.row(align=True)
- sub.label(text="Lock:") # based on other stuff...
- sub.operator("gpencil.stroke_lock_color", icon='BORDER_RECT', text="")
- sub.operator("gpencil.palette_lock_layer", icon='COLOR', text="")
-
- pcolor = palette.colors.active
- if pcolor:
- self.draw_palettecolors(layout, pcolor)
-
- # Draw palette colors
- def draw_palettecolors(self, layout, pcolor):
- # color settings
- split = layout.split(percentage=0.5)
- split.active = not pcolor.lock
-
- # Column 1 - Stroke
- col = split.column(align=True)
- col.enabled = not pcolor.lock
- col.label(text="Stroke:")
- col.prop(pcolor, "color", text="")
- col.prop(pcolor, "alpha", slider=True)
-
- # Column 2 - Fill
- col = split.column(align=True)
- col.enabled = not pcolor.lock
- col.label(text="Fill:")
- col.prop(pcolor, "fill_color", text="")
- col.prop(pcolor, "fill_alpha", text="Opacity", slider=True)
-
- # Options
- split = layout.split(percentage=0.5)
- split.active = not pcolor.lock
-
- col = split.column(align=True)
- col.active = not pcolor.lock
- col.prop(pcolor, "use_volumetric_strokes")
- col = split.column(align=True)
- col.active = not pcolor.lock
- col.prop(pcolor, "use_hq_fill")
+###############################
class GreasePencilToolsPanel:
# For use in "2D" Editors without their own toolbar
@@ -1150,6 +835,7 @@ class GreasePencilToolsPanel:
# bl_options = {'DEFAULT_CLOSED'}
bl_label = "Grease Pencil Settings"
bl_region_type = 'UI'
+ bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
@@ -1183,20 +869,23 @@ class GreasePencilToolsPanel:
gpencil_stroke_placement_settings(context, layout)
+###############################
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_separate,
+
GPENCIL_MT_gpencil_edit_specials,
- GPENCIL_UL_brush,
- GPENCIL_UL_palettecolor,
- GPENCIL_UL_layer,
- GPENCIL_MT_layer_specials,
- GPENCIL_MT_brush_specials,
- GPENCIL_MT_palettecolor_specials,
+ GPENCIL_MT_gpencil_sculpt_specials,
+ GPENCIL_MT_gpencil_draw_specials,
+ GPENCIL_MT_gpencil_draw_delete,
+
+ GPENCIL_UL_annotation_layer,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 0e3e50b3497..5d12f762073 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -86,8 +86,11 @@ class EEVEE_MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
@classmethod
def poll(cls, context):
- engine = context.engine
- return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)
+ if context.active_object and context.active_object.type == 'GPENCIL':
+ return False
+ else:
+ engine = context.engine
+ return (context.material or context.object) and (engine in cls.COMPAT_ENGINES)
def draw(self, context):
layout = self.layout
diff --git a/release/scripts/startup/bl_ui/properties_material_gpencil.py b/release/scripts/startup/bl_ui/properties_material_gpencil.py
new file mode 100644
index 00000000000..2d823594547
--- /dev/null
+++ b/release/scripts/startup/bl_ui/properties_material_gpencil.py
@@ -0,0 +1,322 @@
+# ##### 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 #####
+
+# <pep8 compliant>
+import bpy
+from bpy.types import Menu, Panel, UIList
+from rna_prop_ui import PropertyPanel
+
+
+class GPENCIL_MT_color_specials(Menu):
+ bl_label = "Layer"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("gpencil.color_reveal", icon='RESTRICT_VIEW_OFF', text="Show All")
+ layout.operator("gpencil.color_hide", icon='RESTRICT_VIEW_ON', text="Hide Others").unselected = True
+
+ layout.separator()
+
+ layout.operator("gpencil.color_lock_all", icon='LOCKED', text="Lock All")
+ layout.operator("gpencil.color_unlock_all", icon='UNLOCKED', text="UnLock All")
+
+ layout.separator()
+
+ layout.operator("gpencil.stroke_lock_color", icon='BORDER_RECT', text="Lock Unselected")
+ layout.operator("gpencil.lock_layer", icon='COLOR', text="Lock Unused")
+
+
+class GPENCIL_UL_matslots(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ slot = item
+ ma = slot.material
+ if (ma is not None) and (ma.grease_pencil is not None):
+ gpcolor = ma.grease_pencil
+
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ if gpcolor.lock:
+ layout.active = False
+
+ row = layout.row(align=True)
+ row.enabled = not gpcolor.lock
+ row.prop(ma, "name", text="", emboss=False, icon_value=icon)
+
+ row = layout.row(align=True)
+ row.prop(gpcolor, "lock", text="", emboss=False)
+ row.prop(gpcolor, "hide", text="", emboss=False)
+ if gpcolor.ghost is True:
+ icon = 'GHOST_DISABLED'
+ else:
+ icon = 'GHOST_ENABLED'
+ row.prop(gpcolor, "ghost", text="", icon=icon, emboss=False)
+
+ elif self.layout_type == 'GRID':
+ layout.alignment = 'CENTER'
+ layout.label(text="", icon_value=icon)
+
+
+class GPMaterialButtonsPanel:
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "material"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return (ob and ob.type == 'GPENCIL' and
+ ob.active_material and
+ ob.active_material.grease_pencil)
+
+
+
+class MATERIAL_PT_gpencil_slots(Panel):
+ bl_label = "Grease Pencil Material Slots"
+ bl_space_type = 'PROPERTIES'
+ bl_region_type = 'WINDOW'
+ bl_context = "material"
+ bl_options = {'HIDE_HEADER'}
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ return ob and ob.type == 'GPENCIL'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ gpd = context.gpencil_data
+
+ mat = context.object.active_material
+ ob = context.object
+ slot = context.material_slot
+ space = context.space_data
+
+ if ob:
+ is_sortable = len(ob.material_slots) > 1
+ rows = 1
+ if (is_sortable):
+ rows = 4
+
+ row = layout.row()
+
+ row.template_list("GPENCIL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=rows)
+
+ col = row.column(align=True)
+ col.operator("object.material_slot_add", icon='ZOOMIN', text="")
+ col.operator("object.material_slot_remove", icon='ZOOMOUT', text="")
+
+ col.menu("GPENCIL_MT_color_specials", 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='LOCKED', text="").affect_visibility = False
+ sub.operator("gpencil.color_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True
+
+ row = layout.row()
+
+ if ob:
+ row.template_ID(ob, "active_material", new="material.new", live_icon=True)
+
+ if slot:
+ icon_link = 'MESH_DATA' if slot.link == 'DATA' else 'OBJECT_DATA'
+ row.prop(slot, "link", icon=icon_link, icon_only=True)
+
+ if gpd.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.operator("gpencil.stroke_change_color", text="Assign")
+ row.operator("gpencil.color_select", text="Select")
+
+ elif mat:
+ row.template_ID(space, "pin_id")
+
+
+# Used as parent for "Stroke" and "Fill" panels
+class MATERIAL_PT_gpencil_surface(GPMaterialButtonsPanel, Panel):
+ bl_label = "Surface"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.object
+ ma = context.object.active_material
+ if ma is None or ma.grease_pencil is None:
+ return False
+
+ return ob and ob.type == 'GPENCIL'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+
+class MATERIAL_PT_gpencil_strokecolor(GPMaterialButtonsPanel, Panel):
+ bl_label = "Stroke"
+ bl_parent_id = 'MATERIAL_PT_gpencil_surface'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ma = context.object.active_material
+ if ma is not None and ma.grease_pencil is not None:
+ gpcolor = ma.grease_pencil
+
+ col = layout.column()
+ col.active = not gpcolor.lock
+
+ col.prop(gpcolor, "mode")
+
+ col.prop(gpcolor, "stroke_style", text="Style")
+
+ if gpcolor.stroke_style == 'TEXTURE':
+ row = col.row()
+ row.enabled = not gpcolor.lock
+ col = row.column(align=True)
+ col.template_ID(gpcolor, "stroke_image", open="image.open")
+ col.prop(gpcolor, "pixel_size", text="UV Factor")
+ col.prop(gpcolor, "use_stroke_pattern", text="Use As Pattern")
+
+ if gpcolor.stroke_style == 'SOLID' or gpcolor.use_stroke_pattern is True:
+ col.prop(gpcolor, "color", text="Color")
+
+
+class MATERIAL_PT_gpencil_fillcolor(GPMaterialButtonsPanel, Panel):
+ bl_label = "Fill"
+ bl_parent_id = 'MATERIAL_PT_gpencil_surface'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ma = context.object.active_material
+ if ma is not None and ma.grease_pencil:
+ gpcolor = ma.grease_pencil
+
+ # color settings
+ col = layout.column()
+ col.active = not gpcolor.lock
+ col.prop(gpcolor, "fill_style", text="Style")
+
+ if gpcolor.fill_style == 'GRADIENT':
+ col.prop(gpcolor, "gradient_type")
+
+ if gpcolor.fill_style != 'TEXTURE':
+ col.prop(gpcolor, "fill_color", text="Color")
+
+ if gpcolor.fill_style in ('GRADIENT', 'CHESSBOARD'):
+ col.prop(gpcolor, "mix_color", text="Secondary Color")
+
+ if gpcolor.fill_style == 'GRADIENT':
+ col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
+
+ if gpcolor.fill_style in ('GRADIENT', 'CHESSBOARD'):
+ col.prop(gpcolor, "flip", text="Flip Colors")
+
+ col.prop(gpcolor, "pattern_shift", text="Location")
+ col.prop(gpcolor, "pattern_scale", text="Scale")
+
+ if gpcolor.gradient_type == 'RADIAL' and gpcolor.fill_style not in ('SOLID', 'CHESSBOARD'):
+ col.prop(gpcolor, "pattern_radius", text="Radius")
+ else:
+ if gpcolor.fill_style != 'SOLID':
+ col.prop(gpcolor, "pattern_angle", text="Angle")
+
+ if gpcolor.fill_style == 'CHESSBOARD':
+ col.prop(gpcolor, "pattern_gridsize", text="Box Size")
+
+ # Texture
+ if gpcolor.fill_style == 'TEXTURE' or (gpcolor.texture_mix is True and gpcolor.fill_style == 'SOLID'):
+ col.template_ID(gpcolor, "fill_image", open="image.open")
+
+ if gpcolor.fill_style == 'TEXTURE':
+ col.prop(gpcolor, "use_fill_pattern", text="Use As Pattern")
+ if gpcolor.use_fill_pattern is True:
+ col.prop(gpcolor, "fill_color", text="Color")
+
+ col.prop(gpcolor, "texture_offset", text="Offset")
+ col.prop(gpcolor, "texture_scale", text="Scale")
+ col.prop(gpcolor, "texture_angle")
+ col.prop(gpcolor, "texture_opacity")
+ col.prop(gpcolor, "texture_clamp", text="Clip Image")
+
+ if gpcolor.use_fill_pattern is False:
+ col.prop(gpcolor, "texture_mix", text="Mix With Color")
+
+ if gpcolor.texture_mix is True:
+ col.prop(gpcolor, "fill_color", text="Mix Color")
+ col.prop(gpcolor, "mix_factor", text="Mix Factor", slider=True)
+
+
+class MATERIAL_PT_gpencil_preview(GPMaterialButtonsPanel, Panel):
+ bl_label = "Preview"
+ COMPAT_ENGINES = {'BLENDER_EEVEE'}
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw(self, context):
+ ma = context.object.active_material
+ self.layout.label(ma.name)
+ self.layout.template_preview(ma)
+
+
+class MATERIAL_PT_gpencil_custom_props(GPMaterialButtonsPanel, PropertyPanel, Panel):
+ COMPAT_ENGINES = {'BLENDER_EEVEE', 'BLENDER_OPENGL'}
+ _context_path = "object.active_material"
+ _property_type = bpy.types.Material
+
+
+class MATERIAL_PT_gpencil_options(GPMaterialButtonsPanel, Panel):
+ bl_label = "Options"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ ma = context.object.active_material
+ if ma is not None and ma.grease_pencil is not None:
+ gpcolor = ma.grease_pencil
+ layout.prop(gpcolor, "pass_index")
+
+
+classes = (
+ GPENCIL_UL_matslots,
+ GPENCIL_MT_color_specials,
+ MATERIAL_PT_gpencil_slots,
+ MATERIAL_PT_gpencil_preview,
+ MATERIAL_PT_gpencil_surface,
+ MATERIAL_PT_gpencil_strokecolor,
+ MATERIAL_PT_gpencil_fillcolor,
+ MATERIAL_PT_gpencil_options,
+ MATERIAL_PT_gpencil_custom_props,
+)
+
+if __name__ == "__main__": # only for live edit.
+ from bpy.utils import register_class
+ for cls in classes:
+ register_class(cls)
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 38bfc6ad294..91be9bb5d0a 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -28,9 +28,9 @@ from rna_prop_ui import PropertyPanel
from bl_operators.presets import PresetMenu
from .properties_physics_common import (
- point_cache_ui,
- effector_weights_ui,
-)
+ point_cache_ui,
+ effector_weights_ui,
+ )
class SCENE_PT_units_length_presets(PresetMenu):
@@ -104,7 +104,6 @@ class SCENE_PT_unit(SceneButtonsPanel, Panel):
col.prop(unit, "scale_length")
col.prop(unit, "use_separate")
-
class SceneKeyingSetsPanel:
@staticmethod
@@ -568,6 +567,33 @@ class SCENE_PT_simplify_render(SceneButtonsPanel, Panel):
col.prop(rd, "simplify_child_particles_render", text="Max Child Particles")
+class SCENE_PT_simplify_greasepencil(SceneButtonsPanel, Panel):
+ bl_label = "Simplify Grease Pencil"
+ COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header(self, context):
+ rd = context.scene.render
+ self.layout.prop(rd, "simplify_gpencil", text="")
+
+ def draw(self, context):
+ layout = self.layout
+
+ rd = context.scene.render
+
+ layout.active = rd.simplify_gpencil
+
+ row = layout.row()
+ row.prop(rd, "simplify_gpencil_onplay", text="Only on Play")
+
+ split = layout.split()
+
+ col = split.column()
+ col.prop(rd, "simplify_gpencil_view_fill", text="Fill")
+ col.prop(rd, "simplify_gpencil_remove_lines", text="Remove Fill Lines")
+ col.prop(rd, "simplify_gpencil_view_modifier", text="Modifiers")
+
+
class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel):
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_OPENGL'}
_context_path = "scene"
@@ -593,6 +619,7 @@ classes = (
SCENE_PT_simplify,
SCENE_PT_simplify_viewport,
SCENE_PT_simplify_render,
+ SCENE_PT_simplify_greasepencil,
SCENE_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index 23c3e97ac9a..8e32d98529b 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -23,14 +23,8 @@ from bpy.types import Panel, Header, Menu, UIList
from bpy.app.translations import pgettext_iface as iface_
from bl_operators.presets import PresetMenu
from .properties_grease_pencil_common import (
- GreasePencilDrawingToolsPanel,
- GreasePencilStrokeEditPanel,
- GreasePencilStrokeSculptPanel,
- GreasePencilBrushPanel,
- GreasePencilBrushCurvesPanel,
- GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
-)
+ GreasePencilDrawingToolsPanel,
+ GreasePencilDataPanel)
class CLIP_UL_tracking_objects(UIList):
@@ -1154,40 +1148,12 @@ class CLIP_PT_grease_pencil(GreasePencilDataPanel, CLIP_PT_clip_view_panel, Pane
# But, this should only be visible in "clip" view
-# Grease Pencil palette colors
-class CLIP_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, CLIP_PT_clip_view_panel, Panel):
- bl_space_type = 'CLIP_EDITOR'
- bl_region_type = 'UI'
- bl_options = {'DEFAULT_CLOSED'}
-
- # NOTE: this is just a wrapper around the generic GP Panel
- # But, this should only be visible in "clip" view
-
-
# Grease Pencil drawing tools
class CLIP_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
bl_space_type = 'CLIP_EDITOR'
+ bl_region_type = 'TOOLS'
-# Grease Pencil stroke editing tools
-class CLIP_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
-
-
-# Grease Pencil stroke sculpting tools
-class CLIP_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
-
-
-# Grease Pencil drawing brushes
-class CLIP_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
-
-
-# Grease Pencil drawing curves
-class CLIP_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
- bl_space_type = 'CLIP_EDITOR'
-
class CLIP_MT_view(Menu):
bl_label = "View"
@@ -1515,12 +1481,7 @@ classes = (
CLIP_PT_footage_info,
CLIP_PT_tools_scenesetup,
CLIP_PT_grease_pencil,
- CLIP_PT_grease_pencil_palettecolor,
CLIP_PT_tools_grease_pencil_draw,
- CLIP_PT_tools_grease_pencil_edit,
- CLIP_PT_tools_grease_pencil_sculpt,
- CLIP_PT_tools_grease_pencil_brush,
- CLIP_PT_tools_grease_pencil_brushcurves,
CLIP_MT_view,
CLIP_MT_clip,
CLIP_MT_proxy,
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 1303e46ab6c..501f58e9901 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -21,20 +21,15 @@ import bpy
import math
from bpy.types import Header, Menu, Panel, UIList
from .properties_paint_common import (
- UnifiedPaintPanel,
- brush_texture_settings,
- brush_texpaint_common,
- brush_mask_texture_settings,
-)
+ UnifiedPaintPanel,
+ brush_texture_settings,
+ brush_texpaint_common,
+ brush_mask_texture_settings,
+ )
from .properties_grease_pencil_common import (
- GreasePencilDrawingToolsPanel,
- GreasePencilStrokeEditPanel,
- GreasePencilStrokeSculptPanel,
- GreasePencilBrushPanel,
- GreasePencilBrushCurvesPanel,
- GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
-)
+ GreasePencilDrawingToolsPanel,
+ GreasePencilDataPanel
+ )
from bpy.app.translations import pgettext_iface as iface_
@@ -1346,39 +1341,12 @@ class IMAGE_PT_grease_pencil(GreasePencilDataPanel, Panel):
# NOTE: this is just a wrapper around the generic GP Panel
-
-# Grease Pencil palette colors
-class IMAGE_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
- bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
-
-
# Grease Pencil drawing tools
class IMAGE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
bl_space_type = 'IMAGE_EDITOR'
+ bl_region_type = 'TOOLS'
-# Grease Pencil stroke editing tools
-class IMAGE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
-
-
-# Grease Pencil stroke sculpting tools
-class IMAGE_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
-
-
-# Grease Pencil drawing brushes
-class IMAGE_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
-
-
-# Grease Pencil drawing curves
-class IMAGE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
- bl_space_type = 'IMAGE_EDITOR'
-
classes = (
IMAGE_MT_view,
@@ -1430,12 +1398,7 @@ classes = (
IMAGE_PT_sample_line,
IMAGE_PT_scope_sample,
IMAGE_PT_grease_pencil,
- IMAGE_PT_grease_pencil_palettecolor,
IMAGE_PT_tools_grease_pencil_draw,
- IMAGE_PT_tools_grease_pencil_edit,
- IMAGE_PT_tools_grease_pencil_sculpt,
- IMAGE_PT_tools_grease_pencil_brush,
- IMAGE_PT_tools_grease_pencil_brushcurves,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index 45343c09b27..affbf70b1a0 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -23,15 +23,10 @@ from bpy.types import Header, Menu, Panel
from bpy.app.translations import pgettext_iface as iface_
from bl_operators.presets import PresetMenu
from .properties_grease_pencil_common import (
- GreasePencilDrawingToolsPanel,
- GreasePencilStrokeEditPanel,
- GreasePencilStrokeSculptPanel,
- GreasePencilBrushPanel,
- GreasePencilBrushCurvesPanel,
- GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
- GreasePencilToolsPanel
-)
+ GreasePencilDrawingToolsPanel,
+ GreasePencilDataPanel,
+ GreasePencilToolsPanel
+ )
class NODE_HT_header(Header):
@@ -539,19 +534,6 @@ class NODE_PT_grease_pencil(GreasePencilDataPanel, Panel):
return snode is not None and snode.node_tree is not None
-# Grease Pencil palette colors
-class NODE_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
-
- @classmethod
- def poll(cls, context):
- snode = context.space_data
- return snode is not None and snode.node_tree is not None
-
-
class NODE_PT_grease_pencil_tools(GreasePencilToolsPanel, Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
@@ -571,31 +553,6 @@ class NODE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
bl_region_type = 'TOOLS'
-# Grease Pencil stroke editing tools
-class NODE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'TOOLS'
-
-
-# Grease Pencil stroke sculpting tools
-class NODE_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'TOOLS'
-
-# Grease Pencil drawing brushes
-
-
-class NODE_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'TOOLS'
-
-# Grease Pencil drawing curves
-
-
-class NODE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
- bl_space_type = 'NODE_EDITOR'
- bl_region_type = 'TOOLS'
-
# -----------------------------
@@ -620,13 +577,8 @@ classes = (
NODE_PT_quality,
NODE_UL_interface_sockets,
NODE_PT_grease_pencil,
- NODE_PT_grease_pencil_palettecolor,
NODE_PT_grease_pencil_tools,
NODE_PT_tools_grease_pencil_draw,
- NODE_PT_tools_grease_pencil_edit,
- NODE_PT_tools_grease_pencil_sculpt,
- NODE_PT_tools_grease_pencil_brush,
- NODE_PT_tools_grease_pencil_brushcurves,
)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index bac462dcbab..84ae59772b6 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -22,7 +22,6 @@ from bpy.types import Header, Menu, Panel
from rna_prop_ui import PropertyPanel
from .properties_grease_pencil_common import (
GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
GreasePencilToolsPanel,
)
from bpy.app.translations import pgettext_iface as iface_
@@ -1281,14 +1280,6 @@ class SEQUENCER_PT_grease_pencil(GreasePencilDataPanel, SequencerButtonsPanel_Ou
# But, it should only show up when there are images in the preview region
-class SEQUENCER_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, SequencerButtonsPanel_Output, Panel):
- bl_space_type = 'SEQUENCE_EDITOR'
- bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
- # But, it should only show up when there are images in the preview region
-
-
class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsPanel_Output, Panel):
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
@@ -1333,7 +1324,6 @@ classes = (
SEQUENCER_PT_view_safe_areas,
SEQUENCER_PT_modifiers,
SEQUENCER_PT_grease_pencil,
- SEQUENCER_PT_grease_pencil_palettecolor,
SEQUENCER_PT_grease_pencil_tools,
SEQUENCER_PT_custom_props,
)
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 3101ffc8336..b682588629b 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -24,6 +24,7 @@
# For now keep this in a single file since it's an area that may change,
# so avoid making changes all over the place.
+import bpy
from bpy.types import Panel
from .space_toolsystem_common import (
@@ -39,21 +40,77 @@ def generate_from_brushes_ex(
brush_category_attr,
brush_category_layout,
):
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_paint.draw_settings_common(context, layout, tool)
+
# Categories
brush_categories = {}
- for brush in context.blend_data.brushes:
- if getattr(brush, brush_test_attr):
- category = getattr(brush, brush_category_attr)
- name = brush.name
- brush_categories.setdefault(category, []).append(
- ToolDef.from_dict(
- dict(
- text=name,
- icon=icon_prefix + category.lower(),
- data_block=name,
+ if context.mode != 'GPENCIL_PAINT':
+ for brush in context.blend_data.brushes:
+ if getattr(brush, brush_test_attr) and brush.gpencil_settings is None:
+ category = getattr(brush, brush_category_attr)
+ name = brush.name
+ brush_categories.setdefault(category, []).append(
+ ToolDef.from_dict(
+ dict(
+ text=name,
+ icon=icon_prefix + category.lower(),
+ data_block=name,
+ )
)
)
- )
+ else:
+ for brush_type in brush_category_layout:
+ for brush in context.blend_data.brushes:
+ if getattr(brush, brush_test_attr) and brush.gpencil_settings.gp_icon == brush_type[0]:
+ category = brush_type[0]
+ name = brush.name
+
+ # rename default brushes for tool bar
+ if name.startswith("Draw "):
+ text = name.replace("Draw ", "")
+ elif name.startswith("Eraser "):
+ text = name.replace("Eraser ", "")
+ elif name.startswith("Fill "):
+ text = name.replace(" Area", "")
+ else:
+ text = name
+
+ # define icon
+ gp_icon = brush.gpencil_settings.gp_icon
+ if gp_icon == 'PENCIL':
+ icon_name = 'draw_pencil'
+ elif gp_icon == 'PEN':
+ icon_name = 'draw_pen'
+ elif gp_icon == 'INK':
+ icon_name = 'draw_ink'
+ elif gp_icon == 'INKNOISE':
+ icon_name = 'draw_noise'
+ elif gp_icon == 'BLOCK':
+ icon_name = 'draw_block'
+ elif gp_icon == 'MARKER':
+ icon_name = 'draw_marker'
+ elif gp_icon == 'FILL':
+ icon_name = 'draw_fill'
+ elif gp_icon == 'SOFT':
+ icon_name = 'draw.eraser_soft'
+ elif gp_icon == 'HARD':
+ icon_name = 'draw.eraser_hard'
+ elif gp_icon == 'STROKE':
+ icon_name = 'draw.eraser_stroke'
+
+ brush_categories.setdefault(category, []).append(
+ ToolDef.from_dict(
+ dict(
+ text=text,
+ icon=icon_prefix + icon_name,
+ data_block=name,
+ widget=None,
+ operator="gpencil.draw",
+ draw_settings=draw_settings,
+ )
+ )
+ )
def tools_from_brush_group(groups):
assert(type(groups) is tuple)
@@ -61,6 +118,7 @@ def generate_from_brushes_ex(
tool_defs = tuple(brush_categories.pop(groups[0], ()))
else:
tool_defs = tuple(item for g in groups for item in brush_categories.pop(g, ()))
+
if len(tool_defs) > 1:
return (tool_defs,)
else:
@@ -125,6 +183,112 @@ class _defs_view3d_generic:
)
+class _defs_annotate:
+ @classmethod
+ def draw_settings_common(cls, context, layout, tool):
+ user_prefs = context.user_preferences
+ ts = context.tool_settings
+
+ # XXX: These context checks are needed for layer-dependent settings,
+ # but this breaks for using topbar for 2D editor active tools, etc.
+ if type(context.gpencil_data_owner) is bpy.types.Object:
+ gpd = context.scene.grease_pencil
+ else:
+ gpd = context.gpencil_data
+
+ gpl = gpd.layers.active if gpd else None
+
+ if gpd and gpl:
+ layout.prop(gpd.layers, "active_note", text="")
+ layout.prop(gpl, "thickness", text="Thickness")
+ else:
+ layout.prop(user_prefs.edit, "grease_pencil_default_color", text="Color")
+ layout.prop(ts, "annotation_thickness", text="Thickness")
+
+ # For 3D view, show the stroke placement settings
+ # XXX: How to tell what editor the active tool comes from?
+ is_3d_view = True
+ if is_3d_view:
+ layout.separator()
+
+ row = layout.row(align=True)
+ row.prop(ts, "annotation_stroke_placement_view3d", text="Orientation")
+ if ts.gpencil_stroke_placement_view3d == 'CURSOR':
+ row.prop(ts.gpencil_sculpt, "lockaxis")
+ elif ts.gpencil_stroke_placement_view3d in {'SURFACE', 'STROKE'}:
+ row.prop(ts, "use_gpencil_stroke_endpoints")
+
+ @ToolDef.from_fn
+ def scribble():
+ def draw_settings(context, layout, tool):
+ _defs_annotate.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Annotate",
+ icon="ops.gpencil.draw",
+ cursor='PAINT_BRUSH',
+ keymap=(
+ ("gpencil.annotate",
+ dict(mode='DRAW', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def line():
+ def draw_settings(context, layout, tool):
+ _defs_annotate.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Draw Line",
+ icon="ops.gpencil.draw.line",
+ cursor='CROSSHAIR',
+ keymap=(
+ ("gpencil.annotate",
+ dict(mode='DRAW_STRAIGHT', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def poly():
+ def draw_settings(context, layout, tool):
+ _defs_annotate.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Draw Polygon",
+ icon="ops.gpencil.draw.poly",
+ cursor='CROSSHAIR',
+ keymap=(
+ ("gpencil.annotate",
+ dict(mode='DRAW_POLY', wait_for_input=False),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def eraser():
+ def draw_settings(context, layout, tool):
+ # TODO: Move this setting to toolsettings
+ user_prefs = context.user_preferences
+ layout.prop(user_prefs.edit, "grease_pencil_eraser_radius", text="Radius")
+
+ return dict(
+ text="Eraser",
+ icon="ops.gpencil.draw.eraser",
+ cursor='CROSSHAIR', # XXX: Always show brush circle when enabled
+ keymap=(
+ ("gpencil.annotate",
+ dict(mode='ERASER', wait_for_input=False),
+ dict(type='ACTIONMOUSE', value='PRESS')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+
class _defs_transform:
@ToolDef.from_fn
@@ -865,6 +1029,331 @@ class _defs_uv_select:
),
)
+class _defs_gpencil_paint:
+ @classmethod
+ def draw_color_selector(cls, context, layout):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ ts = context.tool_settings
+ row = layout.row(align=True)
+ row.prop(ts, "use_gpencil_thumbnail_list", text="", icon="IMGDISPLAY")
+ if ts.use_gpencil_thumbnail_list is False:
+ row.template_ID(gp_settings, "material", live_icon=True)
+ else:
+ row.template_greasepencil_color(gp_settings, "material", rows=3, cols=8, scale=0.8)
+
+ @classmethod
+ def draw_settings_common(cls, context, layout, tool):
+ ob = context.active_object
+ if ob and ob.mode == 'GPENCIL_PAINT':
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ tool_settings= context.tool_settings
+
+ if gp_settings.gpencil_brush_type == 'ERASE':
+ row = layout.row()
+ row.prop(brush, "size", text="Radius")
+ elif gp_settings.gpencil_brush_type == 'FILL':
+ row = layout.row()
+ row.prop(gp_settings, "gpencil_fill_leak", text="Leak Size")
+ row.prop(brush, "size", text="Thickness")
+ row.prop(gp_settings, "gpencil_fill_simplyfy_level", text="Simplify")
+
+ _defs_gpencil_paint.draw_color_selector(context, layout)
+
+ row = layout.row(align=True)
+ row.prop(gp_settings, "gpencil_fill_draw_mode", text="")
+ row.prop(gp_settings, "gpencil_fill_show_boundary", text="", icon='GRID')
+
+ else: # bgpsettings.gpencil_brush_type == 'DRAW':
+ row = layout.row(align=True)
+ row.prop(brush, "size", text="Radius")
+ row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
+ row = layout.row(align=True)
+ row.prop(gp_settings, "pen_strength", slider=True)
+ row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+
+ _defs_gpencil_paint.draw_color_selector(context, layout)
+
+
+ @staticmethod
+ def generate_from_brushes(context):
+ return generate_from_brushes_ex(
+ context,
+ icon_prefix="brush.gpencil.",
+ brush_test_attr="use_paint_grease_pencil",
+ brush_category_attr="grease_pencil_tool",
+ brush_category_layout=(
+ ('PENCIL',),
+ ('PEN',),
+ ('INK',),
+ ('INKNOISE',),
+ ('BLOCK',),
+ ('MARKER',),
+ ('FILL',),
+ ('SOFT',),
+ ('HARD',),
+ ('STROKE',),
+ )
+ )
+
+
+class _defs_gpencil_edit:
+ @ToolDef.from_fn
+ def bend():
+ return dict(
+ text="Bend",
+ icon="ops.gpencil.edit_bend",
+ widget=None,
+ keymap=(
+ ("transform.bend",
+ dict(),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def mirror():
+ return dict(
+ text="Mirror",
+ icon="ops.gpencil.edit_mirror",
+ widget=None,
+ keymap=(
+ ("transform.mirror",
+ dict(),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def shear():
+ return dict(
+ text="Shear",
+ icon="ops.gpencil.edit_shear",
+ widget=None,
+ keymap=(
+ ("transform.shear",
+ dict(),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+ @ToolDef.from_fn
+ def tosphere():
+ return dict(
+ text="To Sphere",
+ icon="ops.gpencil.edit_to_sphere",
+ widget=None,
+ keymap=(
+ ("transform.tosphere",
+ dict(),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ )
+
+
+class _defs_gpencil_sculpt:
+ @classmethod
+ def draw_settings_common(cls, context, layout, tool):
+ ob = context.active_object
+ if ob and ob.mode == 'GPENCIL_SCULPT':
+ ts = context.tool_settings
+ settings = ts.gpencil_sculpt
+ brush = settings.brush
+
+ layout.prop(brush, "size", slider=True)
+
+ row = layout.row(align=True)
+ row.prop(brush, "strength", slider=True)
+ row.prop(brush, "use_pressure_strength", text="")
+ row.separator()
+ row.prop(ts.gpencil_sculpt, "use_select_mask", text="")
+
+ @ToolDef.from_fn
+ def smooth():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Smooth",
+ icon="ops.gpencil.sculpt_smooth",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='SMOOTH', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def thickness():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Thickness",
+ icon="ops.gpencil.sculpt_thickness",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='THICKNESS', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def strength():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Strength",
+ icon="ops.gpencil.sculpt_strength",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='STRENGTH', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def grab():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Grab",
+ icon="ops.gpencil.sculpt_grab",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='GRAB', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def push():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Push",
+ icon="ops.gpencil.sculpt_push",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='PUSH', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def twist():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Twist",
+ icon="ops.gpencil.sculpt_twist",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='TWIST', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def pinch():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Pinch",
+ icon="ops.gpencil.sculpt_pinch",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='PINCH', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def randomize():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Randomize",
+ icon="ops.gpencil.sculpt_randomize",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='RANDOMIZE', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+ @ToolDef.from_fn
+ def clone():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_sculpt.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Clone",
+ icon="ops.gpencil.sculpt_clone",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='CLONE', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
+
+class _defs_gpencil_weight:
+ @classmethod
+ def draw_settings_common(cls, context, layout, tool):
+ ob = context.active_object
+ if ob and ob.mode == 'GPENCIL_WEIGHT':
+ settings = context.tool_settings.gpencil_sculpt
+ brush = settings.brush
+
+ layout.prop(brush, "size", slider=True)
+
+ row = layout.row(align=True)
+ row.prop(brush, "strength", slider=True)
+ row.prop(brush, "use_pressure_strength", text="")
+
+ @ToolDef.from_fn
+ def paint():
+ def draw_settings(context, layout, tool):
+ _defs_gpencil_weight.draw_settings_common(context, layout, tool)
+
+ return dict(
+ text="Draw",
+ icon="ops.gpencil.sculpt_weight",
+ widget=None,
+ keymap=(
+ ("gpencil.brush_paint",
+ dict(mode='WEIGHT', wait_for_input=False),
+ dict(type='EVT_TWEAK_A', value='ANY')),
+ ),
+ draw_settings=draw_settings,
+ )
+
class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
bl_space_type = 'IMAGE_EDITOR'
@@ -951,8 +1440,6 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_transform.scale,
_defs_transform.scale_cage,
),
- None,
- _defs_view3d_generic.ruler,
)
_tools_select = (
@@ -963,6 +1450,16 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
),
)
+ _tools_annotate = (
+ (
+ _defs_annotate.scribble,
+ _defs_annotate.line,
+ _defs_annotate.poly,
+ _defs_annotate.eraser,
+ ),
+ _defs_view3d_generic.ruler,
+ )
+
_tools = {
None: [
_defs_view3d_generic.cursor,
@@ -972,21 +1469,27 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
*_tools_select,
None,
*_tools_transform,
+ None,
+ *_tools_annotate,
],
'POSE': [
*_tools_select,
*_tools_transform,
None,
+ *_tools_annotate,
+ None,
(
_defs_pose.breakdown,
_defs_pose.push,
_defs_pose.relax,
- )
+ ),
],
'EDIT_ARMATURE': [
*_tools_select,
None,
*_tools_transform,
+ None,
+ *_tools_annotate,
_defs_edit_armature.roll,
(
_defs_edit_armature.bone_size,
@@ -996,13 +1499,15 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
(
_defs_edit_armature.extrude,
_defs_edit_armature.extrude_cursor,
- )
+ ),
],
'EDIT_MESH': [
*_tools_select,
None,
*_tools_transform,
None,
+ *_tools_annotate,
+ None,
_defs_edit_mesh.cube_add,
None,
(
@@ -1047,6 +1552,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
None,
*_tools_transform,
None,
+ *_tools_annotate,
+ None,
_defs_edit_curve.draw,
_defs_edit_curve.extrude_cursor,
],
@@ -1075,6 +1582,33 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
None,
_defs_weight_paint.gradient,
],
+ 'GPENCIL_PAINT': [
+ _defs_gpencil_paint.generate_from_brushes,
+ ],
+ 'GPENCIL_EDIT': [
+ *_tools_select,
+ None,
+ *_tools_transform,
+ None,
+ _defs_gpencil_edit.bend,
+ _defs_gpencil_edit.mirror,
+ _defs_gpencil_edit.shear,
+ _defs_gpencil_edit.tosphere,
+ ],
+ 'GPENCIL_SCULPT': [
+ _defs_gpencil_sculpt.smooth,
+ _defs_gpencil_sculpt.thickness,
+ _defs_gpencil_sculpt.strength,
+ _defs_gpencil_sculpt.grab,
+ _defs_gpencil_sculpt.push,
+ _defs_gpencil_sculpt.twist,
+ _defs_gpencil_sculpt.pinch,
+ _defs_gpencil_sculpt.randomize,
+ _defs_gpencil_sculpt.clone,
+ ],
+ 'GPENCIL_WEIGHT': [
+ _defs_gpencil_weight.paint,
+ ],
}
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 55129aa0ce1..0d837ae413a 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -128,6 +128,8 @@ class TOPBAR_HT_lower_bar(Header):
pass
elif mode == 'PARTICLE':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="")
+ elif mode == 'GPENCIL_PAINT':
+ layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".greasepencil_paint", category="")
def draw_center(self, context):
pass
@@ -165,6 +167,15 @@ class TOPBAR_HT_lower_bar(Header):
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".particlemode", category="")
elif mode == 'OBJECT':
layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".objectmode", category="")
+ elif mode == 'GPENCIL_PAINT':
+ layout.prop(context.tool_settings, "gpencil_stroke_placement_view3d", text='')
+ if context.tool_settings.gpencil_stroke_placement_view3d in ('ORIGIN', 'CURSOR'):
+ layout.prop(context.tool_settings.gpencil_sculpt, "lockaxis", text='')
+ layout.prop(context.tool_settings, "use_gpencil_draw_onback", text="", icon='ORTHO')
+ layout.prop(context.tool_settings, "use_gpencil_additive_drawing", text="", icon='FREEZE')
+
+ elif mode == 'GPENCIL_SCULPT':
+ layout.prop(context.tool_settings.gpencil_sculpt, "lockaxis", text='')
class _draw_left_context_mode:
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 53aaff7c4bf..52d4640806d 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -361,14 +361,16 @@ class USERPREF_PT_edit(Panel):
row.separator()
col = row.column()
- col.label(text="Grease Pencil:")
+ col.label(text="Annotations:")
+ sub = col.row()
+ sub.prop(edit, "grease_pencil_default_color", text="Default Color")
col.prop(edit, "grease_pencil_eraser_radius", text="Eraser Radius")
col.separator()
+ col.label(text="Grease Pencil/Annotations:")
+ col.separator()
col.prop(edit, "grease_pencil_manhattan_distance", text="Manhattan Distance")
col.prop(edit, "grease_pencil_euclidean_distance", text="Euclidean Distance")
col.separator()
- col.prop(edit, "grease_pencil_default_color", text="Default Color")
- col.separator()
col.prop(edit, "use_grease_pencil_simplify_stroke", text="Simplify Stroke")
col.separator()
col.separator()
@@ -527,7 +529,10 @@ class USERPREF_PT_system(Panel):
col.prop(system, "gpu_viewport_quality")
col.separator()
+ col.label(text="Grease Pencil Options:")
+ col.prop(system, "gpencil_multi_sample", text="")
+ col.separator()
col.label(text="Text Draw Options:")
col.prop(system, "use_text_antialiasing")
if system.use_text_antialiasing:
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index aed5faff73c..eb595e9f12d 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -19,11 +19,8 @@
# <pep8 compliant>
import bpy
from bpy.types import Header, Menu, Panel
-from .properties_grease_pencil_common import (
- GreasePencilDataPanel,
- GreasePencilPaletteColorPanel,
-)
from .properties_paint_common import UnifiedPaintPanel
+from .properties_grease_pencil_common import GreasePencilDataPanel
from bpy.app.translations import contexts as i18n_contexts
@@ -80,18 +77,40 @@ class VIEW3D_HT_header(Header):
row.operator("pose.paste", text="", icon='PASTEDOWN').flipped = False
row.operator("pose.paste", text="", icon='PASTEFLIPDOWN').flipped = True
- # GPencil
- if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
- row = layout.row(align=True)
- row.operator("gpencil.copy", text="", icon='COPYDOWN')
- row.operator("gpencil.paste", text="", icon='PASTEDOWN')
+ # Grease Pencil
+ if obj and obj.type == 'GPENCIL' and context.gpencil_data:
+ gpd = context.gpencil_data
- # XXX: icon
- layout.prop(context.gpencil_data, "use_onion_skinning", text="Onion Skins", icon='PARTICLE_PATH')
+ if gpd.is_stroke_paint_mode:
+ row = layout.row(align=True)
+ row.popover(
+ panel="VIEW3D_PT_tools_grease_pencil_shapes",
+ text="Shapes"
+ )
- row = layout.row(align=True)
- row.prop(tool_settings.gpencil_sculpt, "use_select_mask")
- row.prop(tool_settings.gpencil_sculpt, "selection_alpha", slider=True)
+ if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode or gpd.is_stroke_weight_mode:
+ row = layout.row(align=True)
+ row.prop(gpd, "use_multiedit", text="", icon="FORCE_HARMONIC")
+
+ sub = row.row(align=True)
+ sub.active = gpd.use_multiedit
+ sub.popover(
+ panel="VIEW3D_PT_gpencil_multi_frame",
+ text="Multiframe"
+ )
+
+ if gpd.use_stroke_edit_mode:
+ row = layout.row(align=True)
+ row.operator("gpencil.copy", text="", icon='COPYDOWN')
+ row.operator("gpencil.paste", text="", icon='PASTEDOWN')
+
+ row = layout.row(align=True)
+ row.prop(tool_settings.gpencil_sculpt, "use_select_mask", text="")
+
+ row.popover(
+ panel="VIEW3D_PT_tools_grease_pencil_interpolate",
+ text="Interpolate"
+ )
VIEW3D_MT_editor_menus.draw_collapsible(context, layout)
@@ -101,7 +120,7 @@ class VIEW3D_HT_header(Header):
scene = context.scene
# Orientation
- if object_mode in {'OBJECT', 'EDIT', 'POSE'}:
+ if object_mode in {'OBJECT', 'EDIT', 'POSE', 'GPENCIL_EDIT'}:
orientation = scene.transform_orientation
current_orientation = scene.current_orientation
@@ -126,7 +145,8 @@ class VIEW3D_HT_header(Header):
if obj is None:
show_snap = True
else:
- if object_mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT'}:
+ if object_mode not in {'SCULPT', 'VERTEX_PAINT', 'WEIGHT_PAINT', 'TEXTURE_PAINT',
+ 'GPENCIL_PAINT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}:
show_snap = True
else:
@@ -160,13 +180,15 @@ class VIEW3D_HT_header(Header):
# Proportional editing
if obj:
- if context.gpencil_data and context.gpencil_data.use_stroke_edit_mode:
- row = layout.row(align=True)
- row.prop(tool_settings, "proportional_edit", icon_only=True)
+ gpd = context.gpencil_data
+ if gpd is not None:
+ if gpd.use_stroke_edit_mode or gpd.is_stroke_sculpt_mode:
+ row = layout.row(align=True)
+ row.prop(tool_settings, "proportional_edit", icon_only=True)
- sub = row.row(align=True)
- sub.active = tool_settings.proportional_edit != 'DISABLED'
- sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
+ sub = row.row(align=True)
+ sub.active = tool_settings.proportional_edit != 'DISABLED'
+ sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
elif object_mode in {'EDIT', 'PARTICLE_EDIT'}:
row = layout.row(align=True)
@@ -190,7 +212,7 @@ class VIEW3D_HT_header(Header):
sub.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
# Pivot
- if object_mode in {'OBJECT', 'EDIT', 'POSE'}:
+ if object_mode in {'OBJECT', 'EDIT', 'POSE', 'GPENCIL_EDIT', 'GPENCIL_SCULPT'}:
pivot_point = tool_settings.transform_pivot_point
act_pivot_point = bpy.types.ToolSettings.bl_rna.properties["transform_pivot_point"].enum_items[pivot_point]
row = layout.row(align=True)
@@ -234,13 +256,14 @@ class VIEW3D_MT_editor_menus(Menu):
obj = context.active_object
mode_string = context.mode
edit_object = context.edit_object
- gp_edit = context.gpencil_data and context.gpencil_data.use_stroke_edit_mode
+ gp_edit = obj and obj.mode in {'GPENCIL_EDIT', 'GPENCIL_PAINT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}
layout.menu("VIEW3D_MT_view")
# Select Menu
if gp_edit:
- layout.menu("VIEW3D_MT_select_gpencil")
+ if mode_string not in {'GPENCIL_PAINT', 'GPENCIL_WEIGHT'}:
+ layout.menu("VIEW3D_MT_select_gpencil")
elif mode_string in {'PAINT_WEIGHT', 'PAINT_VERTEX', 'PAINT_TEXTURE'}:
mesh = obj.data
if mesh.use_paint_mask:
@@ -266,7 +289,15 @@ class VIEW3D_MT_editor_menus(Menu):
layout.menu("INFO_MT_edit_armature_add", text="Add")
if gp_edit:
- layout.menu("VIEW3D_MT_edit_gpencil")
+ if obj and obj.mode == 'GPENCIL_PAINT':
+ layout.menu("VIEW3D_MT_paint_gpencil")
+ elif obj and obj.mode == 'GPENCIL_EDIT':
+ layout.menu("VIEW3D_MT_edit_gpencil")
+ elif obj and obj.mode == 'GPENCIL_SCULPT':
+ layout.menu("VIEW3D_MT_sculpt_gpencil")
+ elif obj and obj.mode == 'GPENCIL_WEIGHT':
+ layout.menu("VIEW3D_MT_weight_gpencil")
+
elif edit_object:
layout.menu("VIEW3D_MT_edit_%s" % edit_object.type.lower())
@@ -1194,6 +1225,7 @@ class VIEW3D_MT_select_gpencil(Menu):
layout.separator()
layout.operator("gpencil.select_linked", text="Linked")
+ layout.operator("gpencil.select_alternate")
layout.operator_menu_enum("gpencil.select_grouped", "type", text="Grouped")
layout.separator()
@@ -1454,6 +1486,7 @@ class INFO_MT_add(Menu):
layout.menu("INFO_MT_armature_add", icon='OUTLINER_OB_ARMATURE')
layout.operator("object.add", text="Lattice", icon='OUTLINER_OB_LATTICE').type = 'LATTICE'
layout.operator_menu_enum("object.empty_add", "type", text="Empty", icon='OUTLINER_OB_EMPTY')
+ layout.operator_menu_enum("object.gpencil_add", "type", text="Grease Pencil", icon='OUTLINER_OB_GREASEPENCIL')
layout.separator()
layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER')
@@ -3110,12 +3143,17 @@ class VIEW3D_MT_edit_gpencil_delete(Menu):
layout.separator()
- layout.operator("gpencil.dissolve")
+ layout.operator_enum("gpencil.dissolve", "type")
layout.separator()
layout.operator("gpencil.active_frames_delete_all")
+ layout.separator()
+
+ layout.operator("gpencil.frame_clean_fill", text="Clean Boundary Strokes").mode = 'ACTIVE'
+ layout.operator("gpencil.frame_clean_fill", text="Clean Boundary Strokes all Frames").mode = 'ALL'
+
# Edit Curve
# draw_curve is used by VIEW3D_MT_edit_curve and VIEW3D_MT_edit_surface
@@ -3476,11 +3514,34 @@ class VIEW3D_MT_edit_armature_delete(Menu):
layout.operator("armature.dissolve", text="Dissolve")
-# ********** GPencil Stroke Edit menu **********
+# ********** Grease Pencil Stroke menus **********
+class VIEW3D_MT_gpencil_simplify(Menu):
+ bl_label = "Simplify"
+
+ def draw(self, context):
+ layout = self.layout
+ layout.operator("gpencil.stroke_simplify_fixed", text="Fixed")
+ layout.operator("gpencil.stroke_simplify", text="Adaptative")
+
+
+class VIEW3D_MT_paint_gpencil(Menu):
+ bl_label = "Strokes"
+
+ def draw(self, context):
+
+ layout = self.layout
+
+ layout.menu("VIEW3D_MT_gpencil_animation")
+ layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
+
+ layout.separator()
+
+ layout.operator("gpencil.delete", text="Delete Frame").type = 'FRAME'
+ layout.operator("gpencil.active_frames_delete_all")
class VIEW3D_MT_edit_gpencil(Menu):
- bl_label = "GPencil"
+ bl_label = "Strokes"
def draw(self, context):
tool_settings = context.tool_settings
@@ -3488,53 +3549,126 @@ class VIEW3D_MT_edit_gpencil(Menu):
layout = self.layout
layout.menu("VIEW3D_MT_edit_gpencil_transform")
- layout.operator("transform.mirror", text="Mirror")
+
+ layout.separator()
layout.menu("GPENCIL_MT_snap")
layout.separator()
- layout.operator("gpencil.brush_paint", text="Sculpt Strokes").wait_for_input = True
- layout.prop_menu_enum(tool_settings.gpencil_sculpt, "tool", text="Sculpt Brush")
+ layout.menu("VIEW3D_MT_gpencil_animation")
layout.separator()
- layout.menu("VIEW3D_MT_object_animation") # NOTE: provides keyingset access...
layout.menu("VIEW3D_MT_edit_gpencil_interpolate")
layout.separator()
layout.operator("gpencil.duplicate_move", text="Duplicate")
layout.operator("gpencil.stroke_subdivide", text="Subdivide")
+ layout.menu("VIEW3D_MT_gpencil_simplify")
layout.separator()
+ layout.operator_menu_enum("gpencil.stroke_separate", "mode", text="Separate...")
+ layout.operator("gpencil.stroke_split", text="Split")
layout.operator_menu_enum("gpencil.stroke_join", "type", text="Join...")
layout.operator("gpencil.stroke_flip", text="Flip Direction")
layout.separator()
layout.operator("gpencil.copy", text="Copy")
- layout.operator("gpencil.paste", text="Paste")
+ layout.operator("gpencil.paste", text="Paste").type = 'COPY'
+ layout.operator("gpencil.paste", text="Paste & Merge").type = 'MERGE'
+
+ layout.separator()
+
+ layout.operator_menu_enum("gpencil.move_to_layer", "layer", text="Move to Layer")
+ layout.operator("gpencil.stroke_change_color", text="Change Color")
+ layout.operator_menu_enum("gpencil.stroke_arrange", "direction", text="Arrange Strokes...")
+
+ layout.separator()
+
+ layout.operator_menu_enum("gpencil.convert", "type", text="Convert to Geometry...")
+
+ layout.separator()
+
+ layout.menu("VIEW3D_MT_edit_gpencil_delete")
+ layout.operator("gpencil.stroke_cyclical_set", text="Toggle Cyclic").type = 'TOGGLE'
+
+ layout.separator()
+
+ layout.operator_menu_enum("gpencil.frame_clean_fill", text="Clean Boundary Strokes...", property="mode")
+
+
+class VIEW3D_MT_sculpt_gpencil(Menu):
+ bl_label = "Strokes"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.menu("VIEW3D_MT_edit_gpencil_transform")
layout.separator()
+ layout.menu("GPENCIL_MT_snap")
- layout.operator("gpencil.reveal")
- layout.operator("gpencil.hide", text="Show Active Layer Only").unselected = True
- layout.operator("gpencil.hide", text="Hide Active Layer").unselected = False
+ layout.separator()
+
+ layout.operator("gpencil.duplicate_move", text="Duplicate")
+ layout.operator("gpencil.stroke_subdivide", text="Subdivide")
+ layout.menu("VIEW3D_MT_gpencil_simplify")
+
+ layout.separator()
+
+ layout.operator_menu_enum("gpencil.stroke_separate", "mode", text="Separate...")
+ layout.operator("gpencil.stroke_split", text="Split")
+ layout.operator_menu_enum("gpencil.stroke_join", "type", text="Join...")
+ layout.operator("gpencil.stroke_flip", text="Flip Direction")
+
+ layout.separator()
+
+ layout.operator("gpencil.copy", text="Copy")
+ layout.operator("gpencil.paste", text="Paste").type = 'COPY'
+ layout.operator("gpencil.paste", text="Paste & Merge").type = 'MERGE'
layout.separator()
layout.operator_menu_enum("gpencil.move_to_layer", "layer", text="Move to Layer")
- layout.operator("gpencil.stroke_change_color", text="Move to Color")
+ layout.operator("gpencil.stroke_change_color", text="Change Color")
layout.operator_menu_enum("gpencil.stroke_arrange", "direction", text="Arrange Strokes...")
layout.separator()
layout.operator_menu_enum("gpencil.convert", "type", text="Convert to Geometry...")
- layout.separator()
- layout.menu("VIEW3D_MT_edit_gpencil_delete")
+class VIEW3D_MT_weight_gpencil(Menu):
+ bl_label = "Weights"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("gpencil.vertex_group_invert", text="Invert")
+ layout.operator("gpencil.vertex_group_smooth", text="Smooth")
+
+
+class VIEW3D_MT_gpencil_animation(Menu):
+ bl_label = "Animation"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ return ob and ob.type == 'GPENCIL' and ob.mode != 'OBJECT'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("gpencil.blank_frame_add")
+ layout.operator("gpencil.active_frames_delete_all", text="Delete Frame(s)")
+
+ layout.separator()
+ layout.operator("gpencil.frame_duplicate", text="Duplicate Active Frame")
+ layout.operator("gpencil.frame_duplicate", text="Duplicate All Layers").mode = 'ALL'
class VIEW3D_MT_edit_gpencil_transform(Menu):
@@ -3595,20 +3729,6 @@ class VIEW3D_MT_view_pie(Menu):
# ********** Panel **********
-class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
-
-
-class VIEW3D_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
- bl_space_type = 'VIEW_3D'
- bl_region_type = 'UI'
-
- # NOTE: this is just a wrapper around the generic GP Panel
-
-
class VIEW3D_PT_view3d_properties(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -3720,6 +3840,7 @@ class VIEW3D_PT_object_type_visibility(Panel):
"armature",
"lattice",
"empty",
+ "grease_pencil",
"camera",
"light",
"light_probe",
@@ -4040,6 +4161,8 @@ class VIEW3D_PT_overlay_guides(Panel):
if shading.type == 'MATERIAL':
col.prop(overlay, "show_look_dev")
+ col.prop(overlay, "show_annotation", text="Annotations")
+
class VIEW3D_PT_overlay_object(Panel):
bl_space_type = 'VIEW_3D'
@@ -4578,6 +4701,60 @@ class VIEW3D_PT_transform_orientations(Panel):
row.operator("transform.delete_orientation", text="", icon='X', emboss=False)
+class VIEW3D_PT_overlay_gpencil_options(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_parent_id = 'VIEW3D_PT_overlay'
+ bl_label = ""
+
+ @classmethod
+ def poll(cls, context):
+ return context.object and context.object.type == 'GPENCIL'
+
+ def draw_header(self, context):
+ layout = self.layout
+ layout.label(text={
+ 'GPENCIL_PAINT': "Draw Grease Pencil",
+ 'GPENCIL_EDIT': "Edit Grease Pencil",
+ 'GPENCIL_SCULPT': "Sculpt Grease Pencil",
+ 'GPENCIL_WEIGHT': "Weight Grease Pencil",
+ 'OBJECT': "Grease Pencil",
+ }[context.mode])
+
+ def draw(self, context):
+ layout = self.layout
+ view = context.space_data
+ overlay = view.overlay
+
+ layout.prop(overlay, "use_gpencil_onion_skin", text="Onion Skin")
+
+ col = layout.column()
+ row = col.row()
+ row.prop(overlay, "use_gpencil_paper", text="")
+ sub = row.row()
+ sub.active = overlay.use_gpencil_paper
+ sub.prop(overlay, "gpencil_paper_opacity", text="Fade 3D Objects", slider=True)
+
+ col = layout.column()
+ row = col.row()
+ row.prop(overlay, "use_gpencil_grid", text="")
+ sub = row.row()
+ sub.active = overlay.use_gpencil_grid
+ sub.prop(overlay, "gpencil_grid_opacity", text="Canvas Grid", slider=True)
+
+ if overlay.use_gpencil_grid:
+ row = layout.row(align=True)
+ row.prop(overlay, "gpencil_grid_scale")
+ col = row.column()
+ col.prop(overlay, "gpencil_grid_lines", text="Subdivisions")
+ col.prop(overlay, "gpencil_grid_axis")
+
+ if context.object.mode in {'GPENCIL_EDIT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}:
+ layout.prop(overlay, "use_gpencil_edit_lines", text="Edit Lines")
+ layout.prop(overlay, "use_gpencil_multiedit_line_only", text="Show Edit Lines only in multiframe")
+ layout.prop(overlay, "vertex_opacity", text="Vertex Opacity", slider=True)
+
+
class VIEW3D_PT_quad_view(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -4605,6 +4782,14 @@ class VIEW3D_PT_quad_view(Panel):
row.prop(region, "use_box_clip")
+# Annotation properties
+class VIEW3D_PT_grease_pencil(GreasePencilDataPanel, Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'UI'
+
+ # NOTE: this is just a wrapper around the generic GP Panel
+
+
class VIEW3D_PT_view3d_stereo(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'UI'
@@ -4684,6 +4869,27 @@ class VIEW3D_PT_context_properties(Panel):
rna_prop_ui.draw(self.layout, context, member, object, False)
+# Grease Pencil Object - Multiframe falloff tools
+class VIEW3D_PT_gpencil_multi_frame(Panel):
+ bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Multi Frame"
+
+ @staticmethod
+ def draw(self, context):
+ gpd = context.gpencil_data
+ settings = context.tool_settings.gpencil_sculpt
+
+ layout = self.layout
+ col = layout.column(align=True)
+ col.prop(settings, "use_multiframe_falloff")
+
+ # Falloff curve
+ if gpd.use_multiedit and settings.use_multiframe_falloff:
+ layout.template_curve_mapping(settings, "multiframe_falloff_curve", brush=True)
+
+
+
classes = (
VIEW3D_HT_header,
VIEW3D_MT_editor_menus,
@@ -4791,8 +4997,13 @@ classes = (
VIEW3D_MT_edit_mesh_clean,
VIEW3D_MT_edit_mesh_delete,
VIEW3D_MT_edit_mesh_showhide,
+ VIEW3D_MT_paint_gpencil,
VIEW3D_MT_edit_gpencil,
VIEW3D_MT_edit_gpencil_delete,
+ VIEW3D_MT_sculpt_gpencil,
+ VIEW3D_MT_weight_gpencil,
+ VIEW3D_MT_gpencil_animation,
+ VIEW3D_MT_gpencil_simplify,
VIEW3D_MT_edit_curve,
VIEW3D_MT_edit_curve_ctrlpoints,
VIEW3D_MT_edit_curve_segments,
@@ -4815,12 +5026,12 @@ classes = (
VIEW3D_MT_edit_gpencil_interpolate,
VIEW3D_MT_object_mode_pie,
VIEW3D_MT_view_pie,
- VIEW3D_PT_grease_pencil,
- VIEW3D_PT_grease_pencil_palettecolor,
VIEW3D_PT_view3d_properties,
VIEW3D_PT_view3d_camera_lock,
VIEW3D_PT_view3d_cursor,
VIEW3D_PT_object_type_visibility,
+ VIEW3D_PT_grease_pencil,
+ VIEW3D_PT_gpencil_multi_frame,
VIEW3D_PT_quad_view,
VIEW3D_PT_view3d_stereo,
VIEW3D_PT_shading,
@@ -4849,6 +5060,7 @@ classes = (
VIEW3D_PT_pivot_point,
VIEW3D_PT_snapping,
VIEW3D_PT_transform_orientations,
+ VIEW3D_PT_overlay_gpencil_options,
VIEW3D_PT_context_properties,
)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 87c6a3840ae..70d8c4089d3 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -20,19 +20,17 @@
import bpy
from bpy.types import Menu, Panel, UIList
from .properties_grease_pencil_common import (
- GreasePencilDrawingToolsPanel,
- GreasePencilStrokeEditPanel,
- GreasePencilInterpolatePanel,
- GreasePencilStrokeSculptPanel,
- GreasePencilBrushPanel,
- GreasePencilBrushCurvesPanel
-)
+ GreasePencilStrokeEditPanel,
+ GreasePencilStrokeSculptPanel,
+ GreasePencilAppearancePanel,
+ )
from .properties_paint_common import (
- UnifiedPaintPanel,
- brush_texture_settings,
- brush_texpaint_common,
- brush_mask_texture_settings,
-)
+ UnifiedPaintPanel,
+ brush_texture_settings,
+ brush_texpaint_common,
+ brush_mask_texture_settings,
+ )
+from bl_operators.presets import PresetMenu
class View3DPanel:
@@ -70,6 +68,12 @@ def draw_vpaint_symmetry(layout, vpaint):
col.use_property_split = True
col.prop(vpaint, "radial_symmetry", text="Radial")
+# Most of these panels should not be visible in GP edit modes
+def is_not_gpencil_edit_mode(context):
+ is_gpmode = context.active_object and \
+ context.active_object.mode in {'GPENCIL_EDIT', 'GPENCIL_PAINT', 'GPENCIL_SCULPT', 'GPENCIL_WEIGHT'}
+ return not is_gpmode
+
# ********** default tools for editmode_mesh ****************
@@ -1341,9 +1345,272 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
sub.prop(pe, "fade_frames", slider=True)
-# Grease Pencil drawing tools
-class VIEW3D_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
+# ********** grease pencil object tool panels ****************
+
+# Grease Pencil drawing brushes
+class VIEW3D_PT_tools_grease_pencil_brush(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Brush"
+
+ @classmethod
+ def poll(cls, context):
+ is_3d_view = context.space_data.type == 'VIEW_3D'
+ if is_3d_view:
+ if context.gpencil_data is None:
+ return False
+
+ gpd = context.gpencil_data
+ return bool(gpd.is_stroke_paint_mode)
+ else:
+ return True
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ ts = context.scene.tool_settings
+ settings = ts.gpencil_paint
+
+ row = layout.row()
+ col = row.column()
+ col.template_ID_preview(settings, "brush", new="brush.add_gpencil", rows=3, cols=8)
+
+ col = row.column()
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+
+ sub = col.column(align=True)
+ sub.operator("gpencil.brush_presets_create", icon='HELP', text="")
+
+ if brush is not None:
+ # XXX: Items in "sub" currently show up beside the brush selector in a separate column
+ if gp_settings.gpencil_brush_type == 'ERASE':
+ sub.prop(gp_settings, "default_eraser", text="")
+
+ # Brush details
+ if gp_settings.gpencil_brush_type == 'ERASE':
+ col = layout.column(align=True)
+ col.prop(brush, "size", text="Radius")
+
+ col.separator()
+ row = col.row()
+ row.prop(gp_settings, "eraser_mode", expand=True)
+ elif gp_settings.gpencil_brush_type == 'FILL':
+ col = layout.column(align=True)
+ col.prop(gp_settings, "gpencil_fill_leak", text="Leak Size")
+ col.prop(brush, "size", text="Thickness")
+ col.prop(gp_settings, "gpencil_fill_simplyfy_level", text="Simplify")
+
+ col = layout.row(align=True)
+ col.template_ID(gp_settings, "material")
+
+ row = layout.row(align=True)
+ row.prop(gp_settings, "gpencil_fill_draw_mode", text="Boundary Draw Mode")
+ row.prop(gp_settings, "gpencil_fill_show_boundary", text="", icon='GRID')
+
+ col = layout.column(align=True)
+ col.enabled = gp_settings.gpencil_fill_draw_mode != "STROKE"
+ col.prop(gp_settings, "gpencil_fill_hide", text="Hide Transparent Lines")
+ sub = col.row(align=True)
+ sub.enabled = gp_settings.gpencil_fill_hide
+ sub.prop(gp_settings, "gpencil_fill_threshold", text="Threshold")
+ else: # bgpsettings.gpencil_brush_type == 'DRAW':
+ row = layout.row(align=True)
+ row.prop(brush, "size", text="Radius")
+ row.prop(gp_settings, "use_pressure", text="", icon='STYLUS_PRESSURE')
+ row = layout.row(align=True)
+ row.prop(gp_settings, "pen_strength", slider=True)
+ row.prop(gp_settings, "use_strength_pressure", text="", icon='STYLUS_PRESSURE')
+
+ row = layout.row(align=True)
+ row.template_ID(gp_settings, "material")
+
+
+# Grease Pencil drawing brushes options
+class VIEW3D_PT_tools_grease_pencil_brush_option(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Options"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_header_preset(self, context):
+ VIEW3D_PT_gpencil_brush_presets.draw_panel_header(self.layout)
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+
+ if brush is not None:
+ col = layout.column(align=True)
+ col.prop(gp_settings, "input_samples")
+ col.separator()
+
+ col.prop(gp_settings, "active_smooth_factor")
+ col.separator()
+
+ col.prop(gp_settings, "angle", slider=True)
+ col.prop(gp_settings, "angle_factor", text="Factor", slider=True)
+ col.separator()
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
+ bl_label = "Stabilizer"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+
+ return brush is not None and gp_settings.gpencil_brush_type == 'DRAW'
+
+ def draw_header(self, context):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ self.layout.prop(gp_settings, "use_stabilizer", text="")
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ layout.active = gp_settings.use_stabilizer
+
+ layout.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
+ layout.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_settings(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
+ bl_label = "Post-processing Settings"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ brush = context.active_gpencil_brush
+
+ return brush is not None
+
+ def draw_header(self, context):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ self.layout.prop(gp_settings, "enable_settings", text="")
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ layout.active = gp_settings.enable_settings
+
+ layout.prop(gp_settings, "pen_smooth_factor")
+ layout.prop(gp_settings, "pen_smooth_steps")
+
+ layout.prop(gp_settings, "pen_thick_smooth_factor")
+ layout.prop(gp_settings, "pen_thick_smooth_steps")
+
+ layout.prop(gp_settings, "pen_subdivision_steps")
+ layout.prop(gp_settings, "random_subdiv", text="Randomness", slider=True)
+
+
+class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_option'
+ bl_label = "Random Settings"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ brush = context.active_gpencil_brush
+
+ return brush is not None
+
+ def draw_header(self, context):
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ self.layout.prop(gp_settings, "enable_random", text="")
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+ layout.active = gp_settings.enable_random
+
+ layout.prop(gp_settings, "random_pressure", text="Pressure", slider=True)
+ layout.prop(gp_settings, "random_strength", text="Strength", slider=True)
+ layout.prop(gp_settings, "uv_random", text="UV", slider=True)
+
+ row = layout.row(align=True)
+ row.prop(gp_settings, "pen_jitter", slider=True)
+ row.prop(gp_settings, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE')
+
+
+# Grease Pencil drawingcurves
+class VIEW3D_PT_tools_grease_pencil_brushcurves(View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Curves"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ brush = context.active_gpencil_brush
+ gp_settings = brush.gpencil_settings
+
+ # Brush
+ layout.label("Sensitivity")
+ layout.template_curve_mapping(gp_settings, "curve_sensitivity", brush=True)
+
+ layout.label("Strength")
+ layout.template_curve_mapping(gp_settings, "curve_strength", brush=True)
+
+ layout.label("Jitter")
+ layout.template_curve_mapping(gp_settings, "curve_jitter", brush=True)
+
+
+# Grease Pencil create shapes
+class VIEW3D_PT_tools_grease_pencil_shapes(View3DPanel, Panel):
bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Shapes"
+
+ @classmethod
+ def poll(cls, context):
+ ob = context.active_object
+ return ob and ob.type == 'GPENCIL'
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ col = layout.column(align=True)
+ col.operator("gpencil.primitive", text="Line", icon='IPO_CONSTANT').type = 'LINE'
+ col.operator("gpencil.primitive", text="Rectangle", icon='UV_FACESEL').type = 'BOX'
+ col.operator("gpencil.primitive", text="Circle", icon='ANTIALIASED').type = 'CIRCLE'
+
+ layout.operator("object.gpencil_add", text="Monkey", icon='MONKEY').type = 'MONKEY'
# Grease Pencil stroke editing tools
@@ -1352,24 +1619,109 @@ class VIEW3D_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
# Grease Pencil stroke interpolation tools
-class VIEW3D_PT_tools_grease_pencil_interpolate(GreasePencilInterpolatePanel, Panel):
+class VIEW3D_PT_tools_grease_pencil_interpolate(Panel):
bl_space_type = 'VIEW_3D'
+ bl_region_type = 'HEADER'
+ bl_label = "Interpolate"
+
+ @classmethod
+ def poll(cls, context):
+ if context.gpencil_data is None:
+ return False
+
+ gpd = context.gpencil_data
+ return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode)
+
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ settings = context.tool_settings.gpencil_interpolate
+
+ col = layout.column(align=True)
+ col.label("Interpolate Strokes")
+ col.operator("gpencil.interpolate", text="Interpolate")
+ col.operator("gpencil.interpolate_sequence", text="Sequence")
+ col.operator("gpencil.interpolate_reverse", text="Remove Breakdowns")
+
+ col = layout.column(align=True)
+ col.label(text="Options:")
+ col.prop(settings, "interpolate_all_layers")
+ col.prop(settings, "interpolate_selected_only")
+
+ col = layout.column(align=True)
+ col.label(text="Sequence Options:")
+ col.prop(settings, "type")
+ if settings.type == 'CUSTOM':
+ # TODO: Options for loading/saving curve presets?
+ col.template_curve_mapping(settings, "interpolation_curve", brush=True)
+ elif settings.type != 'LINEAR':
+ col.prop(settings, "easing")
+
+ if settings.type == 'BACK':
+ layout.prop(settings, "back")
+ elif setting.type == 'ELASTIC':
+ sub = layout.column(align=True)
+ sub.prop(settings, "amplitude")
+ sub.prop(settings, "period")
# Grease Pencil stroke sculpting tools
-class VIEW3D_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
- bl_space_type = 'VIEW_3D'
+class VIEW3D_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, View3DPanel, Panel):
+ bl_context = ".greasepencil_sculpt"
+ bl_category = "Tools"
+ bl_label = "Sculpt Strokes"
-# Grease Pencil drawing brushes
-class VIEW3D_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
- bl_space_type = 'VIEW_3D'
+# Grease Pencil weight painting tools
+class VIEW3D_PT_tools_grease_pencil_weight_paint(View3DPanel, Panel):
+ bl_context = ".greasepencil_weight"
+ bl_category = "Tools"
+ bl_label = "Weight Paint"
-# Grease Pencil drawingcurves
+ @staticmethod
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+ gpd = context.gpencil_data
+ settings = context.tool_settings.gpencil_sculpt
+ tool = settings.tool
+ brush = settings.brush
-class VIEW3D_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
- bl_space_type = 'VIEW_3D'
+ layout.template_icon_view(settings, "weight_tool", show_labels=True)
+
+ col = layout.column()
+ col.prop(brush, "size", slider=True)
+ row = col.row(align=True)
+ row.prop(brush, "strength", slider=True)
+ row.prop(brush, "use_pressure_strength", text="")
+
+ col.prop(brush, "use_falloff")
+
+
+# Grease Pencil Brush Appeareance (one for each mode)
+class VIEW3D_PT_tools_grease_pencil_paint_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
+ bl_context = ".greasepencil_paint"
+ bl_label = "Appearance"
+
+
+class VIEW3D_PT_tools_grease_pencil_sculpt_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
+ bl_context = ".greasepencil_sculpt"
+ bl_label = "Appearance"
+
+
+class VIEW3D_PT_tools_grease_pencil_weight_appearance(GreasePencilAppearancePanel, View3DPanel, Panel):
+ bl_context = ".greasepencil_weight"
+ bl_label = "Appearance"
+
+
+class VIEW3D_PT_gpencil_brush_presets(PresetMenu):
+ """Brush settings"""
+ bl_label = "Brush Presets"
+ preset_subdir = "gpencil_brush"
+ preset_operator = "script.execute_preset"
+ preset_add_operator = "scene.gpencil_brush_preset_add"
classes = (
@@ -1401,12 +1753,21 @@ classes = (
VIEW3D_PT_tools_projectpaint,
VIEW3D_MT_tools_projectpaint_stencil,
VIEW3D_PT_tools_particlemode,
- VIEW3D_PT_tools_grease_pencil_draw,
- VIEW3D_PT_tools_grease_pencil_edit,
- VIEW3D_PT_tools_grease_pencil_interpolate,
- VIEW3D_PT_tools_grease_pencil_sculpt,
+
+ VIEW3D_PT_gpencil_brush_presets,
VIEW3D_PT_tools_grease_pencil_brush,
+ VIEW3D_PT_tools_grease_pencil_brush_option,
+ VIEW3D_PT_tools_grease_pencil_brush_settings,
+ VIEW3D_PT_tools_grease_pencil_brush_stabilizer,
+ VIEW3D_PT_tools_grease_pencil_brush_random,
VIEW3D_PT_tools_grease_pencil_brushcurves,
+ VIEW3D_PT_tools_grease_pencil_shapes,
+ VIEW3D_PT_tools_grease_pencil_sculpt,
+ VIEW3D_PT_tools_grease_pencil_weight_paint,
+ VIEW3D_PT_tools_grease_pencil_paint_appearance,
+ VIEW3D_PT_tools_grease_pencil_sculpt_appearance,
+ VIEW3D_PT_tools_grease_pencil_weight_appearance,
+ VIEW3D_PT_tools_grease_pencil_interpolate,
)
if __name__ == "__main__": # only for live edit.