Vertex Paint: projection options
[blender-staging.git] / release / scripts / startup / bl_ui / space_view3d_toolbar.py
index 2e130a85aaed8243f9e1965fe95cf1b38f692208..798b5e28d9c83150081f55bf87b73d231d382f09 100644 (file)
 
 # <pep8 compliant>
 import bpy
-from bpy.types import Menu, Panel
-from bl_ui.properties_grease_pencil_common import GreasePencilPanel
+from bpy.types import Menu, Panel, UIList
+from bl_ui.properties_grease_pencil_common import (
+        GreasePencilDrawingToolsPanel,
+        GreasePencilStrokeEditPanel,
+        GreasePencilInterpolatePanel,
+        GreasePencilStrokeSculptPanel,
+        GreasePencilBrushPanel,
+        GreasePencilBrushCurvesPanel
+        )
 from bl_ui.properties_paint_common import (
         UnifiedPaintPanel,
         brush_texture_settings,
+        brush_texpaint_common,
         brush_mask_texture_settings,
         )
 
 
-class View3DPanel():
+class View3DPanel:
     bl_space_type = 'VIEW_3D'
     bl_region_type = 'TOOLS'
 
 
 # **************** standard tool clusters ******************
 
-# History/Repeat tools
-def draw_repeat_tools(context, layout):
-    col = layout.column(align=True)
-    col.label(text="Repeat:")
-    col.operator("screen.repeat_last")
-    col.operator("screen.repeat_history", text="History...")
-
-
 # Keyframing tools
 def draw_keyframing_tools(context, layout):
     col = layout.column(align=True)
@@ -51,6 +51,19 @@ def draw_keyframing_tools(context, layout):
     row.operator("anim.keyframe_delete_v3d", text="Remove")
 
 
+# Used by vertex & weight paint
+def draw_vpaint_symmetry(layout, vpaint):
+    col = layout.column(align=True)
+    col.label(text="Mirror:")
+    row = col.row(align=True)
+
+    row.prop(vpaint, "use_symmetry_x", text="X", toggle=True)
+    row.prop(vpaint, "use_symmetry_y", text="Y", toggle=True)
+    row.prop(vpaint, "use_symmetry_z", text="Z", toggle=True)
+
+    col = layout.column()
+    col.prop(vpaint, "radial_symmetry", text="Radial")
+
 # ********** default tools for object-mode ****************
 
 
@@ -104,23 +117,12 @@ class VIEW3D_PT_tools_object(View3DPanel, Panel):
                 row.operator("object.shade_smooth", text="Smooth")
                 row.operator("object.shade_flat", text="Flat")
 
-
-class VIEW3D_PT_tools_objectmode(View3DPanel, Panel):
-    bl_category = "Tools"
-    bl_context = "objectmode"
-    bl_label = "History"
-    bl_options = {'DEFAULT_CLOSED'}
-
-    def draw(self, context):
-        layout = self.layout
-
-        col = layout.column(align=True)
-        row = col.row(align=True)
-        row.operator("ed.undo")
-        row.operator("ed.redo")
-        col.operator("ed.undo_history")
-
-        draw_repeat_tools(context, layout)
+            if obj_type == 'MESH':
+                col = layout.column(align=True)
+                col.label(text="Data Transfer:")
+                row = col.row(align=True)
+                row.operator("object.data_transfer", text="Data")
+                row.operator("object.datalayout_transfer", text="Data Layout")
 
 
 class VIEW3D_PT_tools_add_object(View3DPanel, Panel):
@@ -150,6 +152,7 @@ class VIEW3D_PT_tools_add_object(View3DPanel, Panel):
 
     @staticmethod
     def draw_add_curve(layout, label=False):
+
         if label:
             layout.label(text="Bezier:")
         layout.operator("curve.primitive_bezier_curve_add", text="Bezier", icon='CURVE_BEZCURVE')
@@ -163,6 +166,10 @@ class VIEW3D_PT_tools_add_object(View3DPanel, Panel):
         layout.operator("curve.primitive_nurbs_circle_add", text="Nurbs Circle", icon='CURVE_NCIRCLE')
         layout.operator("curve.primitive_nurbs_path_add", text="Path", icon='CURVE_PATH')
 
+        layout.separator()
+
+        layout.operator("curve.draw", icon='LINE_DATA')
+
     @staticmethod
     def draw_add_surface(layout):
         layout.operator("surface.primitive_nurbs_surface_curve_add", text="Nurbs Curve", icon='SURFACE_NCURVE')
@@ -186,6 +193,7 @@ class VIEW3D_PT_tools_add_object(View3DPanel, Panel):
         layout.operator("object.armature_add", text="Armature", icon='OUTLINER_OB_ARMATURE')
         layout.operator("object.add", text="Lattice", icon='OUTLINER_OB_LATTICE').type = 'LATTICE'
         layout.operator("object.empty_add", text="Empty", icon='OUTLINER_OB_EMPTY').type = 'PLAIN_AXES'
+        layout.operator("object.speaker_add", text="Speaker", icon='OUTLINER_OB_SPEAKER')
         layout.operator("object.camera_add", text="Camera", icon='OUTLINER_OB_CAMERA')
 
     def draw(self, context):
@@ -255,13 +263,19 @@ class VIEW3D_PT_tools_animation(View3DPanel, Panel):
     def draw(self, context):
         layout = self.layout
 
+        ob = context.active_object
+        mpath = ob.motion_path if ob else None
+
         draw_keyframing_tools(context, layout)
 
         col = layout.column(align=True)
         col.label(text="Motion Paths:")
-        row = col.row(align=True)
-        row.operator("object.paths_calculate", text="Calculate")
-        row.operator("object.paths_clear", text="Clear")
+        if mpath:
+            row = col.row(align=True)
+            row.operator("object.paths_update", text="Update")
+            row.operator("object.paths_clear", text="", icon='X')
+        else:
+            col.operator("object.paths_calculate", text="Calculate")
 
         col.separator()
 
@@ -329,7 +343,7 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
         row.operator("transform.vert_slide", text="Vertex")
         col.operator("mesh.noise")
         col.operator("mesh.vertices_smooth")
-        col.operator("object.vertex_random")
+        col.operator("transform.vertex_random")
 
         col = layout.column(align=True)
         col.label(text="Add:")
@@ -337,8 +351,11 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
         col.menu("VIEW3D_MT_edit_mesh_extrude")
         col.operator("view3d.edit_mesh_extrude_move_normal", text="Extrude Region")
         col.operator("view3d.edit_mesh_extrude_individual_move", text="Extrude Individual")
+        col.operator("mesh.inset", text="Inset Faces")
+        col.operator("mesh.edge_face_add")
         col.operator("mesh.subdivide")
         col.operator("mesh.loopcut_slide")
+        col.operator("mesh.offset_edge_loops_slide")
         col.operator("mesh.duplicate_move", text="Duplicate")
         row = col.row(align=True)
         row.operator("mesh.spin")
@@ -360,7 +377,31 @@ class VIEW3D_PT_tools_meshedit(View3DPanel, Panel):
         col.operator_menu_enum("mesh.merge", "type")
         col.operator("mesh.remove_doubles")
 
-        draw_repeat_tools(context, layout)
+
+class VIEW3D_PT_tools_meshweight(View3DPanel, Panel):
+    bl_category = "Tools"
+    bl_context = "mesh_edit"
+    bl_label = "Weight Tools"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    # Used for Weight-Paint mode and Edit-Mode
+    @staticmethod
+    def draw_generic(layout):
+        col = layout.column()
+        col.operator("object.vertex_group_normalize_all", text="Normalize All")
+        col.operator("object.vertex_group_normalize", text="Normalize")
+        col.operator("object.vertex_group_mirror", text="Mirror")
+        col.operator("object.vertex_group_invert", text="Invert")
+        col.operator("object.vertex_group_clean", text="Clean")
+        col.operator("object.vertex_group_quantize", text="Quantize")
+        col.operator("object.vertex_group_levels", text="Levels")
+        col.operator("object.vertex_group_smooth", text="Smooth")
+        col.operator("object.vertex_group_limit_total", text="Limit Total")
+        col.operator("object.vertex_group_fix", text="Fix Deforms")
+
+    def draw(self, context):
+        layout = self.layout
+        self.draw_generic(layout)
 
 
 class VIEW3D_PT_tools_add_mesh_edit(View3DPanel, Panel):
@@ -395,15 +436,16 @@ class VIEW3D_PT_tools_shading(View3DPanel, Panel):
         row.operator("mesh.mark_sharp", text="Sharp")
         col.label(text="Vertices:")
         row = col.row(align=True)
-        op = row.operator("mesh.mark_sharp", text="Smooth")
-        op.use_verts = True
-        op.clear = True
+        props = row.operator("mesh.mark_sharp", text="Smooth")
+        props.use_verts = True
+        props.clear = True
         row.operator("mesh.mark_sharp", text="Sharp").use_verts = True
 
         col = layout.column(align=True)
         col.label(text="Normals:")
         col.operator("mesh.normals_make_consistent", text="Recalculate")
         col.operator("mesh.flip_normals", text="Flip Direction")
+        col.operator("mesh.set_normals_from_faces", text="Set From Faces")
 
 
 class VIEW3D_PT_tools_uvs(View3DPanel, Panel):
@@ -511,9 +553,7 @@ class VIEW3D_PT_tools_curveedit(View3DPanel, Panel):
         col.operator("curve.extrude_move", text="Extrude")
         col.operator("curve.subdivide")
         col.operator("curve.smooth")
-        col.operator("object.vertex_random")
-
-        draw_repeat_tools(context, layout)
+        col.operator("transform.vertex_random")
 
 
 class VIEW3D_PT_tools_add_curve_edit(View3DPanel, Panel):
@@ -528,8 +568,62 @@ class VIEW3D_PT_tools_add_curve_edit(View3DPanel, Panel):
 
         VIEW3D_PT_tools_add_object.draw_add_curve(col, label=True)
 
-# ********** default tools for editmode_surface ****************
 
+class VIEW3D_PT_tools_curveedit_options_stroke(View3DPanel, Panel):
+    bl_category = "Options"
+    bl_context = "curve_edit"
+    bl_label = "Curve Stroke"
+
+    def draw(self, context):
+        layout = self.layout
+
+        tool_settings = context.tool_settings
+        cps = tool_settings.curve_paint_settings
+
+        col = layout.column()
+
+        col.prop(cps, "curve_type")
+
+        if cps.curve_type == 'BEZIER':
+            col.label("Bezier Options:")
+            col.prop(cps, "error_threshold")
+            col.prop(cps, "fit_method")
+            col.prop(cps, "use_corners_detect")
+
+            col = layout.column()
+            col.active = cps.use_corners_detect
+            col.prop(cps, "corner_angle")
+
+        col.label("Pressure Radius:")
+        row = layout.row(align=True)
+        rowsub = row.row(align=True)
+        rowsub.prop(cps, "radius_min", text="Min")
+        rowsub.prop(cps, "radius_max", text="Max")
+
+        row.prop(cps, "use_pressure_radius", text="", icon_only=True)
+
+        col = layout.column()
+        col.label("Taper Radius:")
+        row = layout.row(align=True)
+        row.prop(cps, "radius_taper_start", text="Start")
+        row.prop(cps, "radius_taper_end", text="End")
+
+        col = layout.column()
+        col.label("Projection Depth:")
+        row = layout.row(align=True)
+        row.prop(cps, "depth_mode", expand=True)
+
+        col = layout.column()
+        if cps.depth_mode == 'SURFACE':
+            col.prop(cps, "surface_offset")
+            col.prop(cps, "use_offset_absolute")
+            col.prop(cps, "use_stroke_endpoints")
+            if cps.use_stroke_endpoints:
+                colsub = layout.column(align=True)
+                colsub.prop(cps, "surface_plane", expand=True)
+
+
+# ********** default tools for editmode_surface ****************
 
 class VIEW3D_PT_tools_transform_surface(View3DPanel, Panel):
     bl_category = "Tools"
@@ -563,13 +657,12 @@ class VIEW3D_PT_tools_surfaceedit(View3DPanel, Panel):
         col = layout.column(align=True)
         col.label(text="Modeling:")
         col.operator("curve.extrude", text="Extrude")
+        col.operator("curve.spin")
         col.operator("curve.subdivide")
 
         col = layout.column(align=True)
         col.label(text="Deform:")
-        col.operator("object.vertex_random")
-
-        draw_repeat_tools(context, layout)
+        col.operator("transform.vertex_random")
 
 
 class VIEW3D_PT_tools_add_surface_edit(View3DPanel, Panel):
@@ -607,25 +700,32 @@ class VIEW3D_PT_tools_textedit(View3DPanel, Panel):
         col.operator("font.style_toggle", text="Italic").style = 'ITALIC'
         col.operator("font.style_toggle", text="Underline").style = 'UNDERLINE'
 
-        draw_repeat_tools(context, layout)
-
 
 # ********** default tools for editmode_armature ****************
 
 
-class VIEW3D_PT_tools_armatureedit(View3DPanel, Panel):
+class VIEW3D_PT_tools_armatureedit_transform(View3DPanel, Panel):
+    bl_category = "Tools"
     bl_context = "armature_edit"
-    bl_label = "Armature Tools"
+    bl_label = "Transform"
 
     def draw(self, context):
         layout = self.layout
 
         col = layout.column(align=True)
-        col.label(text="Transform:")
         col.operator("transform.translate")
         col.operator("transform.rotate")
         col.operator("transform.resize", text="Scale")
 
+
+class VIEW3D_PT_tools_armatureedit(View3DPanel, Panel):
+    bl_category = "Tools"
+    bl_context = "armature_edit"
+    bl_label = "Armature Tools"
+
+    def draw(self, context):
+        layout = self.layout
+
         col = layout.column(align=True)
         col.label(text="Bones:")
         col.operator("armature.bone_primitive_add", text="Add")
@@ -639,12 +739,11 @@ class VIEW3D_PT_tools_armatureedit(View3DPanel, Panel):
 
         col = layout.column(align=True)
         col.label(text="Deform:")
-        col.operator("object.vertex_random")
-
-        draw_repeat_tools(context, layout)
+        col.operator("transform.vertex_random")
 
 
 class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
+    bl_category = "Options"
     bl_context = "armature_edit"
     bl_label = "Armature Options"
 
@@ -653,6 +752,7 @@ class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel):
 
         self.layout.prop(arm, "use_mirror_x")
 
+
 # ********** default tools for editmode_mball ****************
 
 
@@ -672,9 +772,7 @@ class VIEW3D_PT_tools_mballedit(View3DPanel, Panel):
 
         col = layout.column(align=True)
         col.label(text="Deform:")
-        col.operator("object.vertex_random")
-
-        draw_repeat_tools(context, layout)
+        col.operator("transform.vertex_random")
 
 
 class VIEW3D_PT_tools_add_mball_edit(View3DPanel, Panel):
@@ -712,9 +810,7 @@ class VIEW3D_PT_tools_latticeedit(View3DPanel, Panel):
 
         col = layout.column(align=True)
         col.label(text="Deform:")
-        col.operator("object.vertex_random")
-
-        draw_repeat_tools(context, layout)
+        col.operator("transform.vertex_random")
 
 
 # ********** default tools for pose-mode ****************
@@ -747,18 +843,26 @@ class VIEW3D_PT_tools_posemode(View3DPanel, Panel):
         row.operator("pose.copy", text="Copy")
         row.operator("pose.paste", text="Paste")
 
+        row = layout.row(align=True)
+        row.operator("pose.propagate", text="Propagate")
+        row.menu("VIEW3D_MT_pose_propagate", icon='TRIA_RIGHT', text="")
+
         col = layout.column(align=True)
         col.operator("poselib.pose_add", text="Add To Library")
 
         draw_keyframing_tools(context, layout)
 
+        pchan = context.active_pose_bone
+        mpath = pchan.motion_path if pchan else None
+
         col = layout.column(align=True)
         col.label(text="Motion Paths:")
-        row = col.row(align=True)
-        row.operator("pose.paths_calculate", text="Calculate")
-        row.operator("pose.paths_clear", text="Clear")
-
-        draw_repeat_tools(context, layout)
+        if mpath:
+            row = col.row(align=True)
+            row.operator("pose.paths_update", text="Update")
+            row.operator("pose.paths_clear", text="", icon='X')
+        else:
+            col.operator("pose.paths_calculate", text="Calculate")
 
 
 class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel):
@@ -779,6 +883,67 @@ class View3DPaintPanel(UnifiedPaintPanel):
     bl_region_type = 'TOOLS'
 
 
+class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel):
+    bl_category = "Tools"
+    bl_label = "Missing Data"
+
+    @classmethod
+    def poll(cls, context):
+        toolsettings = context.tool_settings.image_paint
+        return context.image_paint_object and not toolsettings.detect_data()
+
+    def draw(self, context):
+        layout = self.layout
+        toolsettings = context.tool_settings.image_paint
+
+        col = layout.column()
+        col.label("Missing Data", icon='ERROR')
+        if toolsettings.missing_uvs:
+            col.separator()
+            col.label("Missing UVs", icon='INFO')
+            col.label("Unwrap the mesh in edit mode or generate a simple UV layer")
+            col.operator("paint.add_simple_uvs")
+
+        if toolsettings.mode == 'MATERIAL':
+            if toolsettings.missing_materials:
+                col.separator()
+                col.label("Missing Materials", icon='INFO')
+                col.label("Add a material and paint slot below")
+                col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
+            elif toolsettings.missing_texture:
+                ob = context.active_object
+                mat = ob.active_material
+
+                col.separator()
+                if mat:
+                    col.label("Missing Texture Slots", icon='INFO')
+                    col.label("Add a paint slot below")
+                    col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
+                else:
+                    col.label("Missing Materials", icon='INFO')
+                    col.label("Add a material and paint slot below")
+                    col.operator_menu_enum("paint.add_texture_paint_slot", "type", text="Add Paint Slot")
+
+        elif toolsettings.mode == 'IMAGE':
+            if toolsettings.missing_texture:
+                col.separator()
+                col.label("Missing Canvas", icon='INFO')
+                col.label("Add or assign a canvas image below")
+                col.label("Canvas Image:")
+                # todo this should be combinded into a single row
+                col.template_ID(toolsettings, "canvas", open="image.open")
+                col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
+
+        if toolsettings.missing_stencil:
+            col.separator()
+            col.label("Missing Stencil", icon='INFO')
+            col.label("Add or assign a stencil image below")
+            col.label("Stencil Image:")
+            # todo this should be combinded into a single row
+            col.template_ID(toolsettings, "stencil_image", open="image.open")
+            col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
+
+
 class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
     bl_category = "Tools"
     bl_label = "Brush"
@@ -814,14 +979,12 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
                 col.prop(brush, "count")
                 col = layout.column()
                 col.prop(settings, "use_default_interpolate")
-                sub = col.column(align=True)
-                sub.active = settings.use_default_interpolate
-                sub.prop(brush, "steps", slider=True)
-                sub.prop(settings, "default_key_count", slider=True)
+                col.prop(brush, "steps", slider=True)
+                col.prop(settings, "default_key_count", slider=True)
             elif tool == 'LENGTH':
-                layout.prop(brush, "length_mode", expand=True)
+                layout.row().prop(brush, "length_mode", expand=True)
             elif tool == 'PUFF':
-                layout.prop(brush, "puff_mode", expand=True)
+                layout.row().prop(brush, "puff_mode", expand=True)
                 layout.prop(brush, "use_puff_volume")
 
         # Sculpt Mode #
@@ -847,14 +1010,15 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
             self.prop_unified_size(row, context, brush, "use_pressure_size")
 
             # strength, use_strength_pressure, and use_strength_attenuation
-            if capabilities.has_strength:
-                col.separator()
-                row = col.row(align=True)
+            col.separator()
+            row = col.row(align=True)
+
+            if capabilities.has_space_attenuation:
+                row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True)
 
-                if capabilities.has_space_attenuation:
-                    row.prop(brush, "use_space_attenuation", toggle=True, icon_only=True)
+            self.prop_unified_strength(row, context, brush, "strength", text="Strength")
 
-                self.prop_unified_strength(row, context, brush, "strength", text="Strength")
+            if capabilities.has_strength_pressure:
                 self.prop_unified_strength(row, context, brush, "use_pressure_strength")
 
             # auto_smooth_factor and use_inverse_smooth_pressure
@@ -877,6 +1041,12 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
                 row = col.row(align=True)
                 row.prop(brush, "crease_pinch_factor", slider=True, text="Pinch")
 
+            # rake_factor
+            if capabilities.has_rake_factor:
+                col.separator()
+                row = col.row(align=True)
+                row.prop(brush, "rake_factor", slider=True)
+
             # use_original_normal and sculpt_plane
             if capabilities.has_sculpt_plane:
                 col.separator()
@@ -943,25 +1113,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
         # Texture Paint Mode #
 
         elif context.image_paint_object and brush:
-            col = layout.column()
-
-            if brush.image_tool == 'DRAW' and brush.blend not in ('ERASE_ALPHA', 'ADD_ALPHA'):
-                col.template_color_picker(brush, "color", value_slider=True)
-                col.prop(brush, "color", text="")
-
-            row = col.row(align=True)
-            self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
-            self.prop_unified_size(row, context, brush, "use_pressure_size")
-
-            row = col.row(align=True)
-            self.prop_unified_strength(row, context, brush, "strength", text="Strength")
-            self.prop_unified_strength(row, context, brush, "use_pressure_strength")
-
-            col.prop(brush, "blend", text="Blend")
-
-            col = layout.column()
-            col.active = (brush.blend not in {'ERASE_ALPHA', 'ADD_ALPHA'})
-            col.prop(brush, "use_alpha")
+            brush_texpaint_common(self, context, layout, brush, settings, True)
 
         # Weight Paint Mode #
         elif context.weight_paint_object and brush:
@@ -981,6 +1133,10 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
 
             col.prop(brush, "vertex_tool", text="Blend")
 
+            if brush.vertex_tool != 'SMEAR':
+                col.prop(brush, "use_accumulate")
+                col.separator()
+
             col = layout.column()
             col.prop(toolsettings, "use_auto_normalize", text="Auto Normalize")
             col.prop(toolsettings, "use_multipaint", text="Multi-Paint")
@@ -988,9 +1144,16 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
         # Vertex Paint Mode #
         elif context.vertex_paint_object and brush:
             col = layout.column()
-            col.template_color_picker(brush, "color", value_slider=True)
-            col.prop(brush, "color", text="")
+            self.prop_unified_color_picker(col, context, brush, "color", value_slider=True)
+            if settings.palette:
+                col.template_palette(settings, "palette", color=True)
+            row = col.row(align=True)
+            self.prop_unified_color(row, context, brush, "color", text="")
+            self.prop_unified_color(row, context, brush, "secondary_color", text="")
+            row.separator()
+            row.operator("paint.brush_colors_flip", icon='FILE_REFRESH', text="")
 
+            col.separator()
             row = col.row(align=True)
             self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
             self.prop_unified_size(row, context, brush, "use_pressure_size")
@@ -1000,11 +1163,153 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel):
             self.prop_unified_strength(row, context, brush, "use_pressure_strength")
 
             # XXX - TODO
-            #row = col.row(align=True)
-            #row.prop(brush, "jitter", slider=True)
-            #row.prop(brush, "use_pressure_jitter", toggle=True, text="")
-
+            # row = col.row(align=True)
+            # row.prop(brush, "jitter", slider=True)
+            # row.prop(brush, "use_pressure_jitter", toggle=True, text="")
+            col.separator()
             col.prop(brush, "vertex_tool", text="Blend")
+            col.prop(brush, "use_accumulate")
+            col.prop(brush, "use_alpha")
+
+            col.separator()
+            col.template_ID(settings, "palette", new="palette.new")
+
+
+class TEXTURE_UL_texpaintslots(UIList):
+    def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+        mat = data
+
+        if self.layout_type in {'DEFAULT', 'COMPACT'}:
+            layout.prop(item, "name", text="", emboss=False, icon_value=icon)
+            if (not mat.use_nodes) and context.scene.render.engine in {'BLENDER_RENDER', 'BLENDER_GAME'}:
+                mtex_index = mat.texture_paint_slots[index].index
+                layout.prop(mat, "use_textures", text="", index=mtex_index)
+        elif self.layout_type == 'GRID':
+            layout.alignment = 'CENTER'
+            layout.label(text="")
+
+
+class VIEW3D_MT_tools_projectpaint_uvlayer(Menu):
+    bl_label = "Clone Layer"
+
+    def draw(self, context):
+        layout = self.layout
+
+        for i, tex in enumerate(context.active_object.data.uv_textures):
+            props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
+            props.data_path = "active_object.data.uv_textures.active_index"
+            props.value = i
+
+
+class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel):
+    bl_context = "imagepaint"
+    bl_label = "Slots"
+    bl_category = "Slots"
+
+    @classmethod
+    def poll(cls, context):
+        brush = context.tool_settings.image_paint.brush
+        ob = context.active_object
+        return (brush is not None and ob is not None)
+
+    def draw(self, context):
+        layout = self.layout
+
+        settings = context.tool_settings.image_paint
+        # brush = settings.brush
+
+        ob = context.active_object
+        col = layout.column()
+
+        col.label("Painting Mode:")
+        col.prop(settings, "mode", text="")
+        col.separator()
+
+        if settings.mode == 'MATERIAL':
+            if len(ob.material_slots) > 1:
+                col.label("Materials:")
+                col.template_list("MATERIAL_UL_matslots", "layers",
+                                  ob, "material_slots",
+                                  ob, "active_material_index", rows=2)
+
+            mat = ob.active_material
+            if mat:
+                col.label("Available Paint Slots:")
+                col.template_list("TEXTURE_UL_texpaintslots", "",
+                                  mat, "texture_paint_images",
+                                  mat, "paint_active_slot", rows=2)
+
+                if mat.texture_paint_slots:
+                    slot = mat.texture_paint_slots[mat.paint_active_slot]
+                else:
+                    slot = None
+
+                if (not mat.use_nodes) and context.scene.render.engine in {'BLENDER_RENDER', 'BLENDER_GAME'}:
+                    row = col.row(align=True)
+                    row.operator_menu_enum("paint.add_texture_paint_slot", "type")
+                    row.operator("paint.delete_texture_paint_slot", text="", icon='X')
+
+                    if slot:
+                        col.prop(mat.texture_slots[slot.index], "blend_type")
+                        col.separator()
+
+                if slot and slot.index != -1:
+                    col.label("UV Map:")
+                    col.prop_search(slot, "uv_layer", ob.data, "uv_textures", text="")
+
+        elif settings.mode == 'IMAGE':
+            mesh = ob.data
+            uv_text = mesh.uv_textures.active.name if mesh.uv_textures.active else ""
+            col.label("Canvas Image:")
+            # todo this should be combinded into a single row
+            col.template_ID(settings, "canvas", open="image.open")
+            col.operator("image.new", text="New").gen_context = 'PAINT_CANVAS'
+            col.label("UV Map:")
+            col.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False)
+
+        col.separator()
+        col.operator("image.save_dirty", text="Save All Images")
+
+
+class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel):
+    bl_context = "imagepaint"
+    bl_label = "Mask"
+    bl_category = "Slots"
+
+    @classmethod
+    def poll(cls, context):
+        brush = context.tool_settings.image_paint.brush
+        ob = context.active_object
+        return (brush is not None and ob is not None)
+
+    def draw_header(self, context):
+        ipaint = context.tool_settings.image_paint
+        self.layout.prop(ipaint, "use_stencil_layer", text="")
+
+    def draw(self, context):
+        layout = self.layout
+
+        toolsettings = context.tool_settings
+        ipaint = toolsettings.image_paint
+        ob = context.active_object
+        mesh = ob.data
+
+        col = layout.column()
+        col.active = ipaint.use_stencil_layer
+
+        stencil_text = mesh.uv_texture_stencil.name if mesh.uv_texture_stencil else ""
+        col.label("UV Map:")
+        col.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
+
+        col.label("Stencil Image:")
+        # todo this should be combinded into a single row
+        col.template_ID(ipaint, "stencil_image", open="image.open")
+        col.operator("image.new", text="New").gen_context = 'PAINT_STENCIL'
+
+        col.label("Visualization:")
+        row = col.row(align=True)
+        row.prop(ipaint, "stencil_color", text="")
+        row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
 
 
 class VIEW3D_PT_tools_brush_overlay(Panel, View3DPaintPanel):
@@ -1089,7 +1394,6 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
 
         settings = self.paint_settings(context)
         brush = settings.brush
-        tex_slot = brush.texture_slot
 
         col = layout.column()
 
@@ -1098,7 +1402,7 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel):
         brush_texture_settings(col, brush, context.sculpt_object)
 
 
-class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
+class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel):
     bl_category = "Tools"
     bl_context = "imagepaint"
     bl_label = "Texture Mask"
@@ -1106,14 +1410,13 @@ class VIEW3D_PT_tools_mask_texture(View3DPanel, Panel):
 
     @classmethod
     def poll(cls, context):
-        brush = context.tool_settings.image_paint.brush
-        return (context.image_paint_object and brush)
+        settings = cls.paint_settings(context)
+        return (settings and settings.brush and context.image_paint_object)
 
     def draw(self, context):
         layout = self.layout
 
         brush = context.tool_settings.image_paint.brush
-        tex_slot_alpha = brush.mask_texture_slot
 
         col = layout.column()
 
@@ -1160,10 +1463,19 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
         if brush.use_space:
             col.separator()
             row = col.row(align=True)
-            row.active = brush.use_space
             row.prop(brush, "spacing", text="Spacing")
             row.prop(brush, "use_pressure_spacing", toggle=True, text="")
 
+        if brush.use_line or brush.use_curve:
+            col.separator()
+            row = col.row(align=True)
+            row.prop(brush, "spacing", text="Spacing")
+
+        if brush.use_curve:
+            col.separator()
+            col.template_ID(brush, "paint_curve", new="paintcurve.new")
+            col.operator("paintcurve.draw")
+
         if context.sculpt_object:
             if brush.sculpt_capabilities.has_jitter:
                 col.separator()
@@ -1200,12 +1512,13 @@ class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel):
             col = layout.column()
             col.separator()
 
-            col.prop(brush, "use_smooth_stroke")
+            if brush.brush_capabilities.has_smooth_stroke:
+                col.prop(brush, "use_smooth_stroke")
 
-            sub = col.column()
-            sub.active = brush.use_smooth_stroke
-            sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
-            sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
+                sub = col.column()
+                sub.active = brush.use_smooth_stroke
+                sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
+                sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
 
         layout.prop(settings, "input_samples")
 
@@ -1229,7 +1542,8 @@ class VIEW3D_PT_tools_brush_curve(Panel, View3DPaintPanel):
 
         layout.template_curve_mapping(brush, "curve", brush=True)
 
-        row = layout.row(align=True)
+        col = layout.column(align=True)
+        row = col.row(align=True)
         row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
         row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
         row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
@@ -1247,6 +1561,15 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
     def poll(cls, context):
         return (context.sculpt_object and context.tool_settings.sculpt)
 
+    def draw_header(self, context):
+        layout = self.layout
+        layout.operator(
+                "sculpt.dynamic_topology_toggle",
+                icon='CHECKBOX_HLT' if context.sculpt_object.use_dynamic_topology_sculpting else 'CHECKBOX_DEHLT',
+                text="",
+                emboss=False,
+                )
+
     def draw(self, context):
         layout = self.layout
 
@@ -1255,19 +1578,16 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel):
         settings = self.paint_settings(context)
         brush = settings.brush
 
-        if context.sculpt_object.use_dynamic_topology_sculpting:
-            layout.operator("sculpt.dynamic_topology_toggle", icon='X', text="Disable Dyntopo")
-        else:
-            layout.operator("sculpt.dynamic_topology_toggle", icon='SCULPT_DYNTOPO', text="Enable Dyntopo")
-
         col = layout.column()
         col.active = context.sculpt_object.use_dynamic_topology_sculpting
         sub = col.column(align=True)
-        sub.active = brush and brush.sculpt_tool not in ('MASK')
+        sub.active = (brush and brush.sculpt_tool != 'MASK')
         if (sculpt.detail_type_method == 'CONSTANT'):
             row = sub.row(align=True)
+            row.prop(sculpt, "constant_detail_resolution")
             row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER')
-            row.prop(sculpt, "constant_detail")
+        elif (sculpt.detail_type_method == 'BRUSH'):
+            sub.prop(sculpt, "detail_percent")
         else:
             sub.prop(sculpt, "detail_size")
         sub.prop(sculpt, "detail_refine_method", text="")
@@ -1293,7 +1613,7 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
 
     def draw(self, context):
         layout = self.layout
-        scene = context.scene
+        scene = context.scene
 
         toolsettings = context.tool_settings
         sculpt = toolsettings.sculpt
@@ -1306,14 +1626,6 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
         col.prop(sculpt, "gravity_object")
         col.separator()
 
-        col = layout.column(align=True)
-        col.label(text="Threads:")
-        col.row(align=True).prop(scene, "omp_threads_mode", expand=True)
-        sub = col.column(align=True)
-        sub.enabled = (scene.omp_threads_mode != 'AUTO')
-        sub.prop(scene, "omp_threads")
-        col.separator()
-
         layout.prop(sculpt, "use_threaded", text="Threaded Sculpt")
         layout.prop(sculpt, "show_low_resolution")
         layout.prop(sculpt, "use_deform_only")
@@ -1324,7 +1636,7 @@ class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel):
 
 class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
     bl_category = "Tools"
-    bl_label = "Symmetry / Lock"
+    bl_label = "Symmetry/Lock"
     bl_options = {'DEFAULT_CLOSED'}
 
     @classmethod
@@ -1353,6 +1665,15 @@ class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel):
         row.prop(sculpt, "lock_y", text="Y", toggle=True)
         row.prop(sculpt, "lock_z", text="Z", toggle=True)
 
+        layout.label(text="Tiling:")
+
+        row = layout.row(align=True)
+        row.prop(sculpt, "tile_x", text="X", toggle=True)
+        row.prop(sculpt, "tile_y", text="Y", toggle=True)
+        row.prop(sculpt, "tile_z", text="Z", toggle=True)
+
+        layout.column().prop(sculpt, "tile_offset", text="Tile Offset")
+
 
 class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
     bl_category = "Options"
@@ -1360,11 +1681,8 @@ class VIEW3D_PT_tools_brush_appearance(Panel, View3DPaintPanel):
 
     @classmethod
     def poll(cls, context):
-        toolsettings = context.tool_settings
-        return ((context.sculpt_object and toolsettings.sculpt) or
-                (context.vertex_paint_object and toolsettings.vertex_paint) or
-                (context.weight_paint_object and toolsettings.weight_paint) or
-                (context.image_paint_object and toolsettings.image_paint))
+        settings = cls.paint_settings(context)
+        return (settings is not None) and (not isinstance(settings, bpy.types.ParticleEdit))
 
     def draw(self, context):
         layout = self.layout
@@ -1409,20 +1727,26 @@ class VIEW3D_PT_tools_weightpaint(View3DPanel, Panel):
 
     def draw(self, context):
         layout = self.layout
+        VIEW3D_PT_tools_meshweight.draw_generic(layout)
 
         col = layout.column()
-        col.operator("object.vertex_group_normalize_all", text="Normalize All")
-        col.operator("object.vertex_group_normalize", text="Normalize")
-        col.operator("object.vertex_group_mirror", text="Mirror")
-        col.operator("object.vertex_group_invert", text="Invert")
-        col.operator("object.vertex_group_clean", text="Clean")
-        col.operator("object.vertex_group_quantize", text="Quantize")
-        col.operator("object.vertex_group_levels", text="Levels")
-        col.operator("object.vertex_group_blend", text="Blend")
-        col.operator("object.vertex_group_transfer_weight", text="Transfer Weights")
-        col.operator("object.vertex_group_limit_total", text="Limit Total")
-        col.operator("object.vertex_group_fix", text="Fix Deforms")
         col.operator("paint.weight_gradient")
+        props = col.operator("object.data_transfer", text="Transfer Weights")
+        props.use_reverse_transfer = True
+        props.data_type = 'VGROUP_WEIGHTS'
+
+
+class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel):
+    bl_category = "Tools"
+    bl_context = "weightpaint"
+    bl_options = {'DEFAULT_CLOSED'}
+    bl_label = "Symmetry"
+
+    def draw(self, context):
+        layout = self.layout
+        toolsettings = context.tool_settings
+        wpaint = toolsettings.weight_paint
+        draw_vpaint_symmetry(layout, wpaint)
 
 
 class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
@@ -1437,9 +1761,16 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
         wpaint = tool_settings.weight_paint
 
         col = layout.column()
+        col.label("Falloff:")
         row = col.row()
-
-        row.prop(wpaint, "use_normal")
+        row.prop(wpaint, "falloff_shape", expand=True)
+        row = col.row()
+        row.prop(wpaint, "use_backface_culling")
+        row = col.row()
+        row.prop(wpaint, "use_normal_falloff")
+        sub = row.row()
+        sub.active = (wpaint.use_normal_falloff)
+        sub.prop(wpaint, "normal_angle", text="")
         col = layout.column()
         row = col.row()
         row.prop(wpaint, "use_spray")
@@ -1455,7 +1786,6 @@ class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel):
 
         col.label("Show Zero Weights:")
         sub = col.row()
-        sub.active = (not tool_settings.use_multipaint)
         sub.prop(tool_settings, "vertex_group_user", expand=True)
 
         self.unified_paint_settings(col, context)
@@ -1475,23 +1805,80 @@ class VIEW3D_PT_tools_vertexpaint(Panel, View3DPaintPanel):
         vpaint = toolsettings.vertex_paint
 
         col = layout.column()
+        col.label("Falloff:")
+        row = col.row()
+        row.prop(vpaint, "falloff_shape", expand=True)
         row = col.row()
-        #col.prop(vpaint, "mode", text="")
-        row.prop(vpaint, "use_normal")
+        row.prop(vpaint, "use_backface_culling")
+        row = col.row()
+        row.prop(vpaint, "use_normal_falloff")
+        sub = row.row()
+        sub.active = (vpaint.use_normal_falloff)
+        sub.prop(vpaint, "normal_angle", text="")
+
         col.prop(vpaint, "use_spray")
 
         self.unified_paint_settings(col, context)
 
-# Commented out because the Apply button isn't an operator yet, making these settings useless
-#~         col.label(text="Gamma:")
-#~         col.prop(vpaint, "gamma", text="")
-#~         col.label(text="Multiply:")
-#~         col.prop(vpaint, "mul", text="")
+
+class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel):
+    bl_category = "Tools"
+    bl_context = "vertexpaint"
+    bl_options = {'DEFAULT_CLOSED'}
+    bl_label = "Symmetry"
+
+    def draw(self, context):
+        layout = self.layout
+        toolsettings = context.tool_settings
+        vpaint = toolsettings.vertex_paint
+        draw_vpaint_symmetry(layout, vpaint)
+
 
 # ********** default tools for texture-paint ****************
 
 
-class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
+class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel):
+    bl_category = "Tools"
+    bl_context = "imagepaint"
+    bl_label = "External"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    def draw(self, context):
+        layout = self.layout
+
+        toolsettings = context.tool_settings
+        ipaint = toolsettings.image_paint
+
+        col = layout.column()
+        row = col.split(align=True, percentage=0.55)
+        row.operator("image.project_edit", text="Quick Edit")
+        row.operator("image.project_apply", text="Apply")
+
+        col.row().prop(ipaint, "screen_grab_size", text="")
+
+        col.operator("paint.project_image", text="Apply Camera Image")
+
+
+class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel):
+    bl_category = "Tools"
+    bl_context = "imagepaint"
+    bl_label = "Symmetry"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    def draw(self, context):
+        layout = self.layout
+
+        toolsettings = context.tool_settings
+        ipaint = toolsettings.image_paint
+
+        col = layout.column(align=True)
+        row = col.row(align=True)
+        row.prop(ipaint, "use_symmetry_x", text="X", toggle=True)
+        row.prop(ipaint, "use_symmetry_y", text="Y", toggle=True)
+        row.prop(ipaint, "use_symmetry_z", text="Z", toggle=True)
+
+
+class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel):
     bl_category = "Options"
     bl_context = "imagepaint"
     bl_label = "Project Paint"
@@ -1504,13 +1891,11 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
     def draw(self, context):
         layout = self.layout
 
-        ob = context.active_object
-        mesh = ob.data
         toolsettings = context.tool_settings
         ipaint = toolsettings.image_paint
-        settings = toolsettings.image_paint
 
         col = layout.column()
+
         col.prop(ipaint, "use_occlude")
         col.prop(ipaint, "use_backface_culling")
 
@@ -1521,35 +1906,13 @@ class VIEW3D_PT_tools_projectpaint(View3DPanel, Panel):
         sub.active = (ipaint.use_normal_falloff)
         sub.prop(ipaint, "normal_angle", text="")
 
-        split = layout.split()
-
-        split.prop(ipaint, "use_stencil_layer", text="Stencil")
-
-        row = split.row()
-        row.active = (ipaint.use_stencil_layer)
-        stencil_text = mesh.uv_texture_stencil.name if mesh.uv_texture_stencil else ""
-        row.menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False)
-        row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA')
-
-        col = layout.column()
-        col.active = (settings.brush.image_tool == 'CLONE')
-        col.prop(ipaint, "use_clone_layer", text="Clone from UV map")
-        clone_text = mesh.uv_texture_clone.name if mesh.uv_texture_clone else ""
-        col.menu("VIEW3D_MT_tools_projectpaint_clone", text=clone_text, translate=False)
+        layout.prop(ipaint, "use_cavity")
+        if ipaint.use_cavity:
+            layout.template_curve_mapping(ipaint, "cavity_curve", brush=True)
 
         layout.prop(ipaint, "seam_bleed")
-
-        col = layout.column()
-        col.label(text="External Editing:")
-
-        row = col.split(align=True, percentage=0.55)
-        row.operator("image.project_edit", text="Quick Edit")
-        row.operator("image.project_apply", text="Apply")
-
-        col.row().prop(ipaint, "screen_grab_size", text="")
-
-        col.operator("paint.project_image", text="Apply Camera Image")
-        col.operator("image.save_dirty", text="Save All Edited")
+        layout.prop(ipaint, "dither")
+        self.unified_paint_settings(layout, context)
 
 
 class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
@@ -1567,18 +1930,6 @@ class VIEW3D_PT_imagepaint_options(View3DPaintPanel):
         self.unified_paint_settings(col, context)
 
 
-class VIEW3D_MT_tools_projectpaint_clone(Menu):
-    bl_label = "Clone Layer"
-
-    def draw(self, context):
-        layout = self.layout
-
-        for i, tex in enumerate(context.active_object.data.uv_textures):
-            props = layout.operator("wm.context_set_int", text=tex.name, translate=False)
-            props.data_path = "active_object.data.uv_texture_clone_index"
-            props.value = i
-
-
 class VIEW3D_MT_tools_projectpaint_stencil(Menu):
     bl_label = "Mask Layer"
 
@@ -1629,7 +1980,7 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
         col = layout.column(align=True)
         if pe.is_hair:
             col.active = pe.is_editable
-            col.prop(pe, "use_emitter_deflect", text="Deflect emitter")
+            col.prop(pe, "use_emitter_deflect", text="Deflect Emitter")
             sub = col.row(align=True)
             sub.active = pe.use_emitter_deflect
             sub.prop(pe, "emitter_distance", text="Distance")
@@ -1644,6 +1995,9 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
             col.prop(pe, "use_auto_velocity", text="Velocity")
         col.prop(ob.data, "use_mirror_x")
 
+        col.prop(pe, "shape_object")
+        col.operator("particle.shape_cut")
+
         col = layout.column(align=True)
         col.active = pe.is_editable
         col.label(text="Draw:")
@@ -1659,12 +2013,125 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
             sub.prop(pe, "fade_frames", slider=True)
 
 
-# Grease Pencil tools
-class VIEW3D_PT_tools_grease_pencil(GreasePencilPanel, Panel):
+# Grease Pencil drawing tools
+class VIEW3D_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
     bl_space_type = 'VIEW_3D'
-    bl_region_type = 'TOOLS'
-    bl_category = "Grease Pencil"
 
 
+# Grease Pencil stroke editing tools
+class VIEW3D_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
+    bl_space_type = 'VIEW_3D'
+
+
+# Grease Pencil stroke interpolation tools
+class VIEW3D_PT_tools_grease_pencil_interpolate(GreasePencilInterpolatePanel, Panel):
+    bl_space_type = 'VIEW_3D'
+
+
+# Grease Pencil stroke sculpting tools
+class VIEW3D_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
+    bl_space_type = 'VIEW_3D'
+
+
+# Grease Pencil drawing brushes
+class VIEW3D_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
+    bl_space_type = 'VIEW_3D'
+
+# Grease Pencil drawingcurves
+class VIEW3D_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
+    bl_space_type = 'VIEW_3D'
+
+
+# Note: moved here so that it's always in last position in 'Tools' panels!
+class VIEW3D_PT_tools_history(View3DPanel, Panel):
+    bl_category = "Tools"
+    # No bl_context, we are always available!
+    bl_label = "History"
+    bl_options = {'DEFAULT_CLOSED'}
+
+    def draw(self, context):
+        layout = self.layout
+        obj = context.object
+
+        col = layout.column(align=True)
+        row = col.row(align=True)
+        row.operator("ed.undo")
+        row.operator("ed.redo")
+        if obj is None or obj.mode != 'SCULPT':
+            # Sculpt mode does not generate an undo menu it seems...
+            col.operator("ed.undo_history")
+
+        col = layout.column(align=True)
+        col.label(text="Repeat:")
+        col.operator("screen.repeat_last")
+        col.operator("screen.repeat_history", text="History...")
+
+
+classes = (
+    VIEW3D_PT_tools_transform,
+    VIEW3D_PT_tools_object,
+    VIEW3D_PT_tools_add_object,
+    VIEW3D_PT_tools_relations,
+    VIEW3D_PT_tools_animation,
+    VIEW3D_PT_tools_rigid_body,
+    VIEW3D_PT_tools_transform_mesh,
+    VIEW3D_PT_tools_meshedit,
+    VIEW3D_PT_tools_meshweight,
+    VIEW3D_PT_tools_add_mesh_edit,
+    VIEW3D_PT_tools_shading,
+    VIEW3D_PT_tools_uvs,
+    VIEW3D_PT_tools_meshedit_options,
+    VIEW3D_PT_tools_transform_curve,
+    VIEW3D_PT_tools_curveedit,
+    VIEW3D_PT_tools_add_curve_edit,
+    VIEW3D_PT_tools_curveedit_options_stroke,
+    VIEW3D_PT_tools_transform_surface,
+    VIEW3D_PT_tools_surfaceedit,
+    VIEW3D_PT_tools_add_surface_edit,
+    VIEW3D_PT_tools_textedit,
+    VIEW3D_PT_tools_armatureedit,
+    VIEW3D_PT_tools_armatureedit_transform,
+    VIEW3D_PT_tools_armatureedit_options,
+    VIEW3D_PT_tools_mballedit,
+    VIEW3D_PT_tools_add_mball_edit,
+    VIEW3D_PT_tools_latticeedit,
+    VIEW3D_PT_tools_posemode,
+    VIEW3D_PT_tools_posemode_options,
+    VIEW3D_PT_imapaint_tools_missing,
+    VIEW3D_PT_tools_brush,
+    TEXTURE_UL_texpaintslots,
+    VIEW3D_MT_tools_projectpaint_uvlayer,
+    VIEW3D_PT_slots_projectpaint,
+    VIEW3D_PT_stencil_projectpaint,
+    VIEW3D_PT_tools_brush_overlay,
+    VIEW3D_PT_tools_brush_texture,
+    VIEW3D_PT_tools_mask_texture,
+    VIEW3D_PT_tools_brush_stroke,
+    VIEW3D_PT_tools_brush_curve,
+    VIEW3D_PT_sculpt_dyntopo,
+    VIEW3D_PT_sculpt_options,
+    VIEW3D_PT_sculpt_symmetry,
+    VIEW3D_PT_tools_brush_appearance,
+    VIEW3D_PT_tools_weightpaint,
+    VIEW3D_PT_tools_weightpaint_symmetry,
+    VIEW3D_PT_tools_weightpaint_options,
+    VIEW3D_PT_tools_vertexpaint,
+    VIEW3D_PT_tools_vertexpaint_symmetry,
+    VIEW3D_PT_tools_imagepaint_external,
+    VIEW3D_PT_tools_imagepaint_symmetry,
+    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_tools_grease_pencil_brush,
+    VIEW3D_PT_tools_grease_pencil_brushcurves,
+    VIEW3D_PT_tools_history,
+)
+
 if __name__ == "__main__":  # only for live edit.
-    bpy.utils.register_module(__name__)
+    from bpy.utils import register_class
+    for cls in classes:
+        register_class(cls)