Hello all.
I am creating an addon for the Grease Pencil interface to improve productivity. I frequently switch between draw, edit, and sculpt modes when creating a drawing and found that picking the mode from the menu is inefficient. So I put together a QuickTool addon for the Grease Pencil that allows toggling between modes with 1 click buttons below the toolbar.
Also included is a shortcut to “Sample Stroke” that allows for adding/removing vertices from the selected stroke with the middle mouse wheel.
My question is, how do I make the “button” icons match the button size in the toolbar?
Thanks in advance for your answers and feedback.
bl_info = {
"name": "GPencil QuickTools",
"author": "pongbuster",
"version": (1, 0),
"blender": (2, 80, 0),
"location": "View3D > Toolbar",
"description": "Adds shortcuts to toggle common modes to toolbar",
"warning": "",
"doc_url": "",
"category": "Grease Pencil",
}
import bpy
class quickEditModeOperator(bpy.types.Operator):
"""
Toggle edit mode
"""
bl_idname = "stroke.editmode"
bl_label = "Toggle Edit Mode"
@classmethod
def poll(self, context):
if context.active_object == None: return False
if context.active_object.type != 'GPENCIL': return False
return context.mode != 'EDIT_GPENCIL'
def execute(self, context):
bpy.ops.gpencil.editmode_toggle()
return {'FINISHED'}
class quickSculptOperator(bpy.types.Operator):
"""
Toggle sculpt mode
"""
bl_idname = "stroke.sculptmode"
bl_label = "Toggle Sculpt Mode"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(self, context):
if context.active_object == None: return False
if context.active_object.type != 'GPENCIL': return False
return context.mode != 'SCULPT_GPENCIL'
def execute(self, context):
bpy.ops.gpencil.sculptmode_toggle()
return {'FINISHED'}
class quickDrawOperator(bpy.types.Operator):
"""
Toggle draw mode
"""
bl_idname = "stroke.drawmode"
bl_label = "Toggle Draw Mode"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(self, context):
if context.active_object == None: return False
if context.active_object.type != 'GPENCIL': return False
return context.mode != 'PAINT_GPENCIL'
def execute(self, context):
bpy.ops.gpencil.paintmode_toggle()
return {'FINISHED'}
sample_length = 0
class quickStrokeSampleOperator(bpy.types.Operator):
"""
Sample selected stroke with new points. Scroll mouse wheel to add / remove number of points.
Left click to apply. Right click to cancel.
"""
bl_idname = "stroke.sample"
bl_label = "Sample Stroke"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(self, context):
return (context.mode == 'SCULPT_GPENCIL' or context.mode == 'EDIT_GPENCIL')
def modal(self, context, event):
global sample_length
if event.type == 'WHEELUPMOUSE':
sample_length -= 0.01
print("sample_length = " + str(sample_length))
bpy.ops.gpencil.stroke_sample(length=sample_length)
elif event.type == 'WHEELDOWNMOUSE':
sample_length += 0.01
print("sample_length = " + str(sample_length))
bpy.ops.gpencil.stroke_sample(length=sample_length)
elif event.type == "LEFTMOUSE":
return {'FINISHED'}
elif event.type in {'RIGHTMOUSE', 'ESC'}:
sample_length = 0.01
bpy.ops.ed.undo()
return {'CANCELLED'}
return {'RUNNING_MODAL'}
def execute(self, context):
global sample_length
print("sample_length = " + str(sample_length))
if sample_length < 0.0001:
sample_length = 0.01
context.tool_settings.use_gpencil_select_mask_stroke=False
context.tool_settings.use_gpencil_select_mask_point=True
bpy.ops.gpencil.stroke_sample(length=sample_length)
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
class QUICK_PT_Tools(bpy.types.Panel):
"""QuickTools"""
bl_label = "QuickTools"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
bl_options = {'HIDE_HEADER'}
@classmethod
def poll(self, context):
if len(context.selected_objects) == 0:
return False
if context.selected_objects[0].type == 'GPENCIL':
return True
return False
def draw(self, context):
layout = self.layout
obj = context.object
row = layout.row()
row.operator(quickEditModeOperator.bl_idname, text="", icon = "EDITMODE_HLT")
row = layout.row()
row.operator(quickDrawOperator.bl_idname, text="", icon = "GPBRUSH_PENCIL")
row = layout.row()
row.operator(quickSculptOperator.bl_idname, text="", icon = "SCULPTMODE_HLT")
layout.row().separator()
row = layout.row()
row.operator(quickStrokeSampleOperator.bl_idname, text="", icon = "STROKE")
# requires to register classes
from bpy.utils import register_class, unregister_class
# Class list to register
_classes = [
quickEditModeOperator,
quickDrawOperator,
quickSculptOperator,
quickStrokeSampleOperator,
QUICK_PT_Tools
]
def register():
for cls in _classes:
register_class(cls)
def unregister():
for cls in _classes:
unregister_class(cls)
if __name__ == "__main__":
register()