1# ##### BEGIN GPL LICENSE BLOCK ##### 2# 3# This program is free software; you can redistribute it and/or 4# modify it under the terms of the GNU General Public License 5# as published by the Free Software Foundation; either version 2 6# of the License, or (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program; if not, write to the Free Software Foundation, 15# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16# 17# ##### END GPL LICENSE BLOCK ##### 18 19# <pep8 compliant> 20from bpy.types import Menu, Panel, UIList 21from bl_ui.properties_grease_pencil_common import ( 22 GreasePencilSculptOptionsPanel, 23 GreasePencilDisplayPanel, 24 GreasePencilBrushFalloff, 25) 26from bl_ui.properties_paint_common import ( 27 UnifiedPaintPanel, 28 BrushSelectPanel, 29 ClonePanel, 30 TextureMaskPanel, 31 ColorPalettePanel, 32 StrokePanel, 33 SmoothStrokePanel, 34 FalloffPanel, 35 DisplayPanel, 36 brush_texture_settings, 37 brush_mask_texture_settings, 38 brush_settings, 39 brush_settings_advanced, 40 draw_color_settings, 41) 42from bl_ui.utils import PresetPanel 43 44 45class VIEW3D_MT_brush_context_menu(Menu): 46 bl_label = "Brush Specials" 47 48 def draw(self, context): 49 layout = self.layout 50 51 settings = UnifiedPaintPanel.paint_settings(context) 52 brush = getattr(settings, "brush", None) 53 54 # skip if no active brush 55 if not brush: 56 layout.label(text="No Brushes currently available", icon='INFO') 57 return 58 59 # brush paint modes 60 layout.menu("VIEW3D_MT_brush_paint_modes") 61 62 # brush tool 63 64 if context.image_paint_object: 65 layout.prop_menu_enum(brush, "image_tool") 66 elif context.vertex_paint_object: 67 layout.prop_menu_enum(brush, "vertex_tool") 68 elif context.weight_paint_object: 69 layout.prop_menu_enum(brush, "weight_tool") 70 elif context.sculpt_object: 71 layout.prop_menu_enum(brush, "sculpt_tool") 72 layout.operator("brush.reset") 73 74 75class VIEW3D_MT_brush_gpencil_context_menu(Menu): 76 bl_label = "Brush Specials" 77 78 def draw(self, context): 79 layout = self.layout 80 ts = context.tool_settings 81 82 settings = None 83 if context.mode == 'PAINT_GPENCIL': 84 settings = ts.gpencil_paint 85 if context.mode == 'SCULPT_GPENCIL': 86 settings = ts.gpencil_sculpt_paint 87 elif context.mode == 'WEIGHT_GPENCIL': 88 settings = ts.gpencil_weight_paint 89 elif context.mode == 'VERTEX_GPENCIL': 90 settings = ts.gpencil_vertex_paint 91 92 brush = getattr(settings, "brush", None) 93 # skip if no active brush 94 if not brush: 95 layout.label(text="No Brushes currently available", icon='INFO') 96 return 97 98 layout.operator("gpencil.brush_reset") 99 layout.operator("gpencil.brush_reset_all") 100 101 102class VIEW3D_MT_brush_context_menu_paint_modes(Menu): 103 bl_label = "Enabled Modes" 104 105 def draw(self, context): 106 layout = self.layout 107 108 settings = UnifiedPaintPanel.paint_settings(context) 109 brush = settings.brush 110 111 layout.prop(brush, "use_paint_sculpt", text="Sculpt") 112 layout.prop(brush, "use_paint_uv_sculpt", text="UV Sculpt") 113 layout.prop(brush, "use_paint_vertex", text="Vertex Paint") 114 layout.prop(brush, "use_paint_weight", text="Weight Paint") 115 layout.prop(brush, "use_paint_image", text="Texture Paint") 116 117 118class View3DPanel: 119 bl_space_type = 'VIEW_3D' 120 bl_region_type = 'UI' 121 122 123# **************** standard tool clusters ****************** 124 125# Used by vertex & weight paint 126def draw_vpaint_symmetry(layout, vpaint, mesh): 127 128 col = layout.column() 129 col.use_property_split = True 130 col.use_property_decorate = False 131 132 row = col.row(heading="Mirror", align=True) 133 row.prop(mesh, "use_mirror_x", text="X", toggle=True) 134 row.prop(mesh, "use_mirror_y", text="Y", toggle=True) 135 row.prop(mesh, "use_mirror_z", text="Z", toggle=True) 136 137 col.prop(vpaint, "radial_symmetry", text="Radial") 138 139 140# Most of these panels should not be visible in GP edit modes 141def is_not_gpencil_edit_mode(context): 142 is_gpmode = ( 143 context.active_object and 144 context.active_object.mode in {'EDIT_GPENCIL', 'PAINT_GPENCIL', 'SCULPT_GPENCIL', 'WEIGHT_GPENCIL'} 145 ) 146 return not is_gpmode 147 148 149# ********** default tools for object mode **************** 150 151 152class VIEW3D_PT_tools_object_options(View3DPanel, Panel): 153 bl_category = "Tool" 154 bl_context = ".objectmode" # dot on purpose (access from topbar) 155 bl_label = "Options" 156 157 def draw(self, context): 158 # layout = self.layout 159 pass 160 161 162class VIEW3D_PT_tools_object_options_transform(View3DPanel, Panel): 163 bl_category = "Tool" 164 bl_context = ".objectmode" # dot on purpose (access from topbar) 165 bl_label = "Transform" 166 bl_parent_id = "VIEW3D_PT_tools_object_options" 167 168 def draw(self, context): 169 layout = self.layout 170 171 layout.use_property_split = True 172 layout.use_property_decorate = False 173 174 tool_settings = context.tool_settings 175 176 col = layout.column(heading="Affect Only", align=True) 177 col.prop(tool_settings, "use_transform_data_origin", text="Origins") 178 col.prop(tool_settings, "use_transform_pivot_point_align", text="Locations") 179 col.prop(tool_settings, "use_transform_skip_children", text="Parents") 180 181 182# ********** default tools for editmode_mesh **************** 183 184 185class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel): 186 bl_category = "Tool" 187 bl_context = ".mesh_edit" # dot on purpose (access from topbar) 188 bl_label = "Options" 189 bl_options = {'DEFAULT_CLOSED'} 190 bl_ui_units_x = 12 191 192 @classmethod 193 def poll(cls, context): 194 return context.active_object 195 196 def draw(self, context): 197 layout = self.layout 198 199 layout.use_property_split = True 200 layout.use_property_decorate = False 201 202 tool_settings = context.tool_settings 203 ob = context.active_object 204 mesh = ob.data 205 206 split = layout.split() 207 208 row = layout.row(align=True, heading="Transform") 209 row.prop(tool_settings, "use_transform_correct_face_attributes") 210 211 row = layout.row(align=True) 212 row.active = tool_settings.use_transform_correct_face_attributes 213 row.prop(tool_settings, "use_transform_correct_keep_connected") 214 215 row = layout.row(align=True, heading="UVs") 216 row.prop(tool_settings, "use_edge_path_live_unwrap") 217 218 row = layout.row(heading="Mirror") 219 sub = row.row(align=True) 220 sub.prop(mesh, "use_mirror_x", text="X", toggle=True) 221 sub.prop(mesh, "use_mirror_y", text="Y", toggle=True) 222 sub.prop(mesh, "use_mirror_z", text="Z", toggle=True) 223 224 row = layout.row(align=True) 225 row.active = ob.data.use_mirror_x or ob.data.use_mirror_y or ob.data.use_mirror_z 226 row.prop(mesh, "use_mirror_topology") 227 228 229class VIEW3D_PT_tools_meshedit_options_automerge(View3DPanel, Panel): 230 bl_category = "Tool" 231 bl_context = ".mesh_edit" # dot on purpose (access from topbar) 232 bl_label = "Auto Merge" 233 bl_parent_id = "VIEW3D_PT_tools_meshedit_options" 234 bl_options = {'DEFAULT_CLOSED'} 235 236 @classmethod 237 def poll(cls, context): 238 return context.active_object 239 240 def draw_header(self, context): 241 tool_settings = context.tool_settings 242 243 self.layout.prop(tool_settings, "use_mesh_automerge", text="", toggle=False) 244 245 def draw(self, context): 246 layout = self.layout 247 248 tool_settings = context.tool_settings 249 250 layout.use_property_split = True 251 layout.use_property_decorate = False 252 253 col = layout.column(align=True) 254 col.active = tool_settings.use_mesh_automerge 255 col.prop(tool_settings, "use_mesh_automerge_and_split", toggle=False) 256 col.prop(tool_settings, "double_threshold", text="Threshold") 257 258 259# ********** default tools for editmode_armature **************** 260 261 262class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel): 263 bl_category = "Tool" 264 bl_context = ".armature_edit" # dot on purpose (access from topbar) 265 bl_label = "Options" 266 267 def draw(self, context): 268 arm = context.active_object.data 269 270 self.layout.prop(arm, "use_mirror_x") 271 272 273# ********** default tools for pose-mode **************** 274 275class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel): 276 bl_category = "Tool" 277 bl_context = ".posemode" # dot on purpose (access from topbar) 278 bl_label = "Pose Options" 279 280 def draw(self, context): 281 pose = context.active_object.pose 282 layout = self.layout 283 284 tool_settings = context.tool_settings 285 286 layout.prop(pose, "use_auto_ik") 287 layout.prop(pose, "use_mirror_x") 288 col = layout.column() 289 col.active = pose.use_mirror_x and not pose.use_auto_ik 290 col.prop(pose, "use_mirror_relative") 291 292 layout.label(text="Affect Only") 293 layout.prop(tool_settings, "use_transform_pivot_point_align", text="Locations") 294 295# ********** default tools for paint modes **************** 296 297 298class TEXTURE_UL_texpaintslots(UIList): 299 def draw_item(self, _context, layout, _data, item, icon, _active_data, _active_propname, _index): 300 # mat = data 301 302 if self.layout_type in {'DEFAULT', 'COMPACT'}: 303 layout.prop(item, "name", text="", emboss=False, icon_value=icon) 304 elif self.layout_type == 'GRID': 305 layout.alignment = 'CENTER' 306 layout.label(text="") 307 308 309class View3DPaintPanel(View3DPanel, UnifiedPaintPanel): 310 bl_category = "Tool" 311 312 313class View3DPaintBrushPanel(View3DPaintPanel): 314 @classmethod 315 def poll(cls, context): 316 mode = cls.get_brush_mode(context) 317 return mode is not None 318 319 320class VIEW3D_PT_tools_particlemode(Panel, View3DPaintPanel): 321 bl_context = ".paint_common" # dot on purpose (access from topbar) 322 bl_label = "Particle Tool" 323 bl_options = {'HIDE_HEADER'} 324 325 @classmethod 326 def poll(cls, context): 327 settings = context.tool_settings.particle_edit 328 return (settings and settings.brush and context.particle_edit_object) 329 330 def draw(self, context): 331 layout = self.layout 332 333 settings = context.tool_settings.particle_edit 334 brush = settings.brush 335 tool = settings.tool 336 337 layout.use_property_split = True 338 layout.use_property_decorate = False # No animation. 339 340 if tool is not None: 341 col = layout.column() 342 col.prop(brush, "size", slider=True) 343 if tool == 'ADD': 344 col.prop(brush, "count") 345 346 col = layout.column() 347 col.prop(settings, "use_default_interpolate") 348 col.prop(brush, "steps", slider=True) 349 col.prop(settings, "default_key_count", slider=True) 350 else: 351 col.prop(brush, "strength", slider=True) 352 353 if tool == 'LENGTH': 354 layout.row().prop(brush, "length_mode", expand=True) 355 elif tool == 'PUFF': 356 layout.row().prop(brush, "puff_mode", expand=True) 357 layout.prop(brush, "use_puff_volume") 358 elif tool == 'COMB': 359 layout.prop(settings, "use_emitter_deflect", text="Deflect Emitter") 360 col = layout.column() 361 col.active = settings.use_emitter_deflect 362 col.prop(settings, "emitter_distance", text="Distance") 363 364 365# TODO, move to space_view3d.py 366class VIEW3D_PT_tools_brush_select(Panel, View3DPaintBrushPanel, BrushSelectPanel): 367 bl_context = ".paint_common" 368 bl_label = "Brushes" 369 370 371# TODO, move to space_view3d.py 372class VIEW3D_PT_tools_brush_settings(Panel, View3DPaintBrushPanel): 373 bl_context = ".paint_common" 374 bl_label = "Brush Settings" 375 376 @classmethod 377 def poll(cls, context): 378 settings = cls.paint_settings(context) 379 return settings and settings.brush is not None 380 381 def draw(self, context): 382 layout = self.layout 383 384 layout.use_property_split = True 385 layout.use_property_decorate = False # No animation. 386 387 settings = self.paint_settings(context) 388 brush = settings.brush 389 390 brush_settings(layout.column(), context, brush, popover=self.is_popover) 391 392 393class VIEW3D_PT_tools_brush_settings_advanced(Panel, View3DPaintBrushPanel): 394 bl_context = ".paint_common" 395 bl_parent_id = "VIEW3D_PT_tools_brush_settings" 396 bl_label = "Advanced" 397 bl_options = {'DEFAULT_CLOSED'} 398 bl_ui_units_x = 14 399 400 def draw(self, context): 401 layout = self.layout 402 403 layout.use_property_split = True 404 layout.use_property_decorate = False # No animation. 405 406 settings = UnifiedPaintPanel.paint_settings(context) 407 brush = settings.brush 408 409 brush_settings_advanced(layout.column(), context, brush, self.is_popover) 410 411 412class VIEW3D_PT_tools_brush_color(Panel, View3DPaintPanel): 413 bl_context = ".paint_common" # dot on purpose (access from topbar) 414 bl_parent_id = "VIEW3D_PT_tools_brush_settings" 415 bl_label = "Color Picker" 416 417 @classmethod 418 def poll(cls, context): 419 settings = cls.paint_settings(context) 420 brush = settings.brush 421 422 if context.image_paint_object: 423 capabilities = brush.image_paint_capabilities 424 return capabilities.has_color 425 elif context.vertex_paint_object: 426 capabilities = brush.vertex_paint_capabilities 427 return capabilities.has_color 428 429 return False 430 431 def draw(self, context): 432 layout = self.layout 433 settings = self.paint_settings(context) 434 brush = settings.brush 435 436 draw_color_settings(context, layout, brush, color_type=not context.vertex_paint_object) 437 438 439class VIEW3D_PT_tools_brush_swatches(Panel, View3DPaintPanel, ColorPalettePanel): 440 bl_context = ".paint_common" 441 bl_parent_id = "VIEW3D_PT_tools_brush_settings" 442 bl_label = "Color Palette" 443 bl_options = {'DEFAULT_CLOSED'} 444 445 446class VIEW3D_PT_tools_brush_clone(Panel, View3DPaintPanel, ClonePanel): 447 bl_context = ".paint_common" 448 bl_parent_id = "VIEW3D_PT_tools_brush_settings" 449 bl_label = "Clone from Paint Slot" 450 bl_options = {'DEFAULT_CLOSED'} 451 452 453class VIEW3D_MT_tools_projectpaint_uvlayer(Menu): 454 bl_label = "Clone Layer" 455 456 def draw(self, context): 457 layout = self.layout 458 459 for i, uv_layer in enumerate(context.active_object.data.uv_layers): 460 props = layout.operator("wm.context_set_int", text=uv_layer.name, translate=False) 461 props.data_path = "active_object.data.uv_layers.active_index" 462 props.value = i 463 464 465class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel): 466 bl_category = "Tool" 467 bl_context = ".imagepaint" # dot on purpose (access from topbar) 468 bl_label = "Texture Slots" 469 470 @classmethod 471 def poll(cls, context): 472 brush = context.tool_settings.image_paint.brush 473 return (brush is not None and context.active_object is not None) 474 475 def draw(self, context): 476 layout = self.layout 477 layout.use_property_split = True 478 layout.use_property_decorate = False 479 480 settings = context.tool_settings.image_paint 481 482 ob = context.active_object 483 484 layout.prop(settings, "mode", text="Mode") 485 layout.separator() 486 487 if settings.mode == 'MATERIAL': 488 if len(ob.material_slots) > 1: 489 layout.template_list("MATERIAL_UL_matslots", "layers", 490 ob, "material_slots", 491 ob, "active_material_index", rows=2) 492 mat = ob.active_material 493 if mat and mat.texture_paint_images: 494 row = layout.row() 495 row.template_list("TEXTURE_UL_texpaintslots", "", 496 mat, "texture_paint_images", 497 mat, "paint_active_slot", rows=2) 498 499 if mat.texture_paint_slots: 500 slot = mat.texture_paint_slots[mat.paint_active_slot] 501 else: 502 slot = None 503 504 have_image = slot is not None 505 else: 506 row = layout.row() 507 508 box = row.box() 509 box.label(text="No Textures") 510 have_image = False 511 512 sub = row.column(align=True) 513 sub.operator_menu_enum("paint.add_texture_paint_slot", "type", icon='ADD', text="") 514 515 elif settings.mode == 'IMAGE': 516 mesh = ob.data 517 uv_text = mesh.uv_layers.active.name if mesh.uv_layers.active else "" 518 layout.template_ID(settings, "canvas", new="image.new", open="image.open") 519 if settings.missing_uvs: 520 layout.operator("paint.add_simple_uvs", icon='ADD', text="Add UVs") 521 else: 522 layout.menu("VIEW3D_MT_tools_projectpaint_uvlayer", text=uv_text, translate=False) 523 have_image = settings.canvas is not None 524 525 layout.prop(settings, "interpolation", text="") 526 527 if settings.missing_uvs: 528 layout.separator() 529 split = layout.split() 530 split.label(text="UV Map Needed", icon='INFO') 531 split.operator("paint.add_simple_uvs", icon='ADD', text="Add Simple UVs") 532 elif have_image: 533 layout.separator() 534 layout.operator("image.save_all_modified", text="Save All Images", icon='FILE_TICK') 535 536 537class VIEW3D_PT_mask(View3DPanel, Panel): 538 bl_category = "Tool" 539 bl_context = ".imagepaint" # dot on purpose (access from topbar) 540 bl_label = "Masking" 541 bl_options = {'DEFAULT_CLOSED'} 542 543 def draw(self, context): 544 pass 545 546 547# TODO, move to space_view3d.py 548class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel): 549 bl_category = "Tool" 550 bl_context = ".imagepaint" # dot on purpose (access from topbar) 551 bl_label = "Stencil Mask" 552 bl_options = {'DEFAULT_CLOSED'} 553 bl_parent_id = "VIEW3D_PT_mask" 554 bl_ui_units_x = 14 555 556 @classmethod 557 def poll(cls, context): 558 brush = context.tool_settings.image_paint.brush 559 ob = context.active_object 560 return (brush is not None and ob is not None) 561 562 def draw_header(self, context): 563 ipaint = context.tool_settings.image_paint 564 self.layout.prop(ipaint, "use_stencil_layer", text="") 565 566 def draw(self, context): 567 layout = self.layout 568 layout.use_property_split = True 569 layout.use_property_decorate = False 570 571 tool_settings = context.tool_settings 572 ipaint = tool_settings.image_paint 573 ob = context.active_object 574 mesh = ob.data 575 576 col = layout.column() 577 col.active = ipaint.use_stencil_layer 578 579 col.label(text="Stencil Image") 580 col.template_ID(ipaint, "stencil_image", new="image.new", open="image.open") 581 582 stencil_text = mesh.uv_layer_stencil.name if mesh.uv_layer_stencil else "" 583 584 col.separator() 585 586 split = col.split() 587 colsub = split.column() 588 colsub.alignment = 'RIGHT' 589 colsub.label(text="UV Layer") 590 split.column().menu("VIEW3D_MT_tools_projectpaint_stencil", text=stencil_text, translate=False) 591 592 col.separator() 593 594 row = col.row(align=True) 595 row.prop(ipaint, "stencil_color", text="Display Color") 596 row.prop(ipaint, "invert_stencil", text="", icon='IMAGE_ALPHA') 597 598 599# TODO, move to space_view3d.py 600class VIEW3D_PT_tools_brush_display(Panel, View3DPaintBrushPanel, DisplayPanel): 601 bl_context = ".paint_common" 602 bl_parent_id = "VIEW3D_PT_tools_brush_settings" 603 bl_label = "Cursor" 604 bl_options = {'DEFAULT_CLOSED'} 605 bl_ui_units_x = 12 606 607 608# TODO, move to space_view3d.py 609class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel): 610 bl_context = ".paint_common" 611 bl_parent_id = "VIEW3D_PT_tools_brush_settings" 612 bl_label = "Texture" 613 bl_options = {'DEFAULT_CLOSED'} 614 615 @classmethod 616 def poll(cls, context): 617 settings = cls.paint_settings(context) 618 return (settings and settings.brush and 619 (context.sculpt_object or context.image_paint_object or context.vertex_paint_object)) 620 621 def draw(self, context): 622 layout = self.layout 623 624 settings = self.paint_settings(context) 625 brush = settings.brush 626 627 col = layout.column() 628 629 col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8) 630 631 brush_texture_settings(col, brush, context.sculpt_object) 632 633 634# TODO, move to space_view3d.py 635class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel, TextureMaskPanel): 636 bl_category = "Tool" 637 bl_context = ".imagepaint" # dot on purpose (access from topbar) 638 bl_parent_id = "VIEW3D_PT_tools_brush_settings" 639 bl_label = "Texture Mask" 640 bl_options = {'DEFAULT_CLOSED'} 641 642 @classmethod 643 def poll(cls, context): 644 settings = cls.paint_settings(context) 645 return (settings and settings.brush and context.image_paint_object) 646 647 def draw(self, context): 648 layout = self.layout 649 650 brush = context.tool_settings.image_paint.brush 651 652 col = layout.column() 653 654 col.template_ID_preview(brush, "mask_texture", new="texture.new", rows=3, cols=8) 655 656 brush_mask_texture_settings(col, brush) 657 658 659# TODO, move to space_view3d.py 660class VIEW3D_PT_tools_brush_stroke(Panel, View3DPaintPanel, StrokePanel): 661 bl_context = ".paint_common" # dot on purpose (access from topbar) 662 bl_label = "Stroke" 663 bl_parent_id = "VIEW3D_PT_tools_brush_settings" 664 bl_options = {'DEFAULT_CLOSED'} 665 666 667class VIEW3D_PT_tools_brush_stroke_smooth_stroke(Panel, View3DPaintPanel, SmoothStrokePanel): 668 bl_context = ".paint_common" # dot on purpose (access from topbar) 669 bl_label = "Stabilize Stroke" 670 bl_parent_id = "VIEW3D_PT_tools_brush_stroke" 671 bl_options = {'DEFAULT_CLOSED'} 672 673 674# TODO, move to space_view3d.py 675class VIEW3D_PT_tools_brush_falloff(Panel, View3DPaintPanel, FalloffPanel): 676 bl_context = ".paint_common" # dot on purpose (access from topbar) 677 bl_parent_id = "VIEW3D_PT_tools_brush_settings" 678 bl_label = "Falloff" 679 bl_options = {'DEFAULT_CLOSED'} 680 681 682class VIEW3D_PT_tools_brush_falloff_frontface(View3DPaintPanel, Panel): 683 bl_context = ".imagepaint" # dot on purpose (access from topbar) 684 bl_label = "Front-face Falloff" 685 bl_parent_id = "VIEW3D_PT_tools_brush_falloff" 686 bl_options = {'DEFAULT_CLOSED'} 687 688 @classmethod 689 def poll(cls, context): 690 return (context.weight_paint_object or context.vertex_paint_object) 691 692 def draw_header(self, context): 693 settings = self.paint_settings(context) 694 brush = settings.brush 695 696 self.layout.prop(brush, "use_frontface_falloff", text="") 697 698 def draw(self, context): 699 settings = self.paint_settings(context) 700 brush = settings.brush 701 702 layout = self.layout 703 704 layout.use_property_split = True 705 layout.use_property_decorate = False 706 707 layout.active = brush.use_frontface_falloff 708 layout.prop(brush, "falloff_angle", text="Angle") 709 710 711class VIEW3D_PT_tools_brush_falloff_normal(View3DPaintPanel, Panel): 712 bl_context = ".imagepaint" # dot on purpose (access from topbar) 713 bl_label = "Normal Falloff" 714 bl_parent_id = "VIEW3D_PT_tools_brush_falloff" 715 bl_options = {'DEFAULT_CLOSED'} 716 717 @classmethod 718 def poll(cls, context): 719 return context.image_paint_object 720 721 def draw_header(self, context): 722 tool_settings = context.tool_settings 723 ipaint = tool_settings.image_paint 724 725 self.layout.prop(ipaint, "use_normal_falloff", text="") 726 727 def draw(self, context): 728 tool_settings = context.tool_settings 729 ipaint = tool_settings.image_paint 730 731 layout = self.layout 732 733 layout.use_property_split = True 734 layout.use_property_decorate = False 735 736 layout.active = ipaint.use_normal_falloff 737 layout.prop(ipaint, "normal_angle", text="Angle") 738 739 740# TODO, move to space_view3d.py 741class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel): 742 bl_context = ".sculpt_mode" # dot on purpose (access from topbar) 743 bl_label = "Dyntopo" 744 bl_options = {'DEFAULT_CLOSED'} 745 bl_ui_units_x = 12 746 747 @classmethod 748 def poll(cls, context): 749 paint_settings = cls.paint_settings(context) 750 return (context.sculpt_object and context.tool_settings.sculpt and paint_settings) 751 752 def draw_header(self, context): 753 is_popover = self.is_popover 754 layout = self.layout 755 layout.operator( 756 "sculpt.dynamic_topology_toggle", 757 icon='CHECKBOX_HLT' if context.sculpt_object.use_dynamic_topology_sculpting else 'CHECKBOX_DEHLT', 758 text="", 759 emboss=is_popover, 760 ) 761 762 def draw(self, context): 763 layout = self.layout 764 layout.use_property_split = True 765 layout.use_property_decorate = False 766 767 tool_settings = context.tool_settings 768 sculpt = tool_settings.sculpt 769 settings = self.paint_settings(context) 770 brush = settings.brush 771 772 col = layout.column() 773 col.active = context.sculpt_object.use_dynamic_topology_sculpting 774 775 sub = col.column() 776 sub.active = (brush and brush.sculpt_tool != 'MASK') 777 if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}: 778 row = sub.row(align=True) 779 row.prop(sculpt, "constant_detail_resolution") 780 props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER') 781 props.mode = 'DYNTOPO' 782 elif (sculpt.detail_type_method == 'BRUSH'): 783 sub.prop(sculpt, "detail_percent") 784 else: 785 sub.prop(sculpt, "detail_size") 786 sub.prop(sculpt, "detail_refine_method", text="Refine Method") 787 sub.prop(sculpt, "detail_type_method", text="Detailing") 788 789 if sculpt.detail_type_method in {'CONSTANT', 'MANUAL'}: 790 col.operator("sculpt.detail_flood_fill") 791 792 col.prop(sculpt, "use_smooth_shading") 793 794 795class VIEW3D_PT_sculpt_voxel_remesh(Panel, View3DPaintPanel): 796 bl_context = ".sculpt_mode" # dot on purpose (access from topbar) 797 bl_label = "Remesh" 798 bl_options = {'DEFAULT_CLOSED'} 799 bl_ui_units_x = 12 800 801 @classmethod 802 def poll(cls, context): 803 return (context.sculpt_object and context.tool_settings.sculpt) 804 805 def draw(self, context): 806 layout = self.layout 807 layout.use_property_split = True 808 layout.use_property_decorate = False 809 810 col = layout.column() 811 mesh = context.active_object.data 812 row = col.row(align=True) 813 row.prop(mesh, "remesh_voxel_size") 814 props = row.operator("sculpt.sample_detail_size", text="", icon='EYEDROPPER') 815 props.mode = 'VOXEL' 816 col.prop(mesh, "remesh_voxel_adaptivity") 817 col.prop(mesh, "use_remesh_fix_poles") 818 col.prop(mesh, "use_remesh_smooth_normals") 819 820 col = layout.column(heading="Preserve", align=True) 821 col.prop(mesh, "use_remesh_preserve_volume", text="Volume") 822 col.prop(mesh, "use_remesh_preserve_paint_mask", text="Paint Mask") 823 col.prop(mesh, "use_remesh_preserve_sculpt_face_sets", text="Face Sets") 824 if context.preferences.experimental.use_sculpt_vertex_colors: 825 col.prop(mesh, "use_remesh_preserve_vertex_colors", text="Vertex Colors") 826 827 layout.operator("object.voxel_remesh", text="Remesh") 828 829 830# TODO, move to space_view3d.py 831class VIEW3D_PT_sculpt_options(Panel, View3DPaintPanel): 832 bl_context = ".sculpt_mode" # dot on purpose (access from topbar) 833 bl_label = "Options" 834 bl_options = {'DEFAULT_CLOSED'} 835 bl_ui_units_x = 12 836 837 @classmethod 838 def poll(cls, context): 839 return (context.sculpt_object and context.tool_settings.sculpt) 840 841 def draw(self, context): 842 layout = self.layout 843 layout.use_property_split = True 844 layout.use_property_decorate = False 845 846 tool_settings = context.tool_settings 847 sculpt = tool_settings.sculpt 848 849 col = layout.column(heading="Display", align=True) 850 col.prop(sculpt, "show_low_resolution") 851 col.prop(sculpt, "use_sculpt_delay_updates") 852 col.prop(sculpt, "use_deform_only") 853 854 col.separator() 855 856 col = layout.column(heading="Auto-Masking", align=True) 857 col.prop(sculpt, "use_automasking_topology", text="Topology") 858 col.prop(sculpt, "use_automasking_face_sets", text="Face Sets") 859 col.prop(sculpt, "use_automasking_boundary_edges", text="Mesh Boundary") 860 col.prop(sculpt, "use_automasking_boundary_face_sets", text="Face Sets Boundary") 861 862 863class VIEW3D_PT_sculpt_options_gravity(Panel, View3DPaintPanel): 864 bl_context = ".sculpt_mode" # dot on purpose (access from topbar) 865 bl_parent_id = "VIEW3D_PT_sculpt_options" 866 bl_label = "Gravity" 867 868 @classmethod 869 def poll(cls, context): 870 return (context.sculpt_object and context.tool_settings.sculpt) 871 872 def draw(self, context): 873 layout = self.layout 874 layout.use_property_split = True 875 layout.use_property_decorate = False 876 877 tool_settings = context.tool_settings 878 sculpt = tool_settings.sculpt 879 capabilities = sculpt.brush.sculpt_capabilities 880 881 col = layout.column() 882 col.active = capabilities.has_gravity 883 col.prop(sculpt, "gravity", slider=True, text="Factor") 884 col.prop(sculpt, "gravity_object") 885 886 887# TODO, move to space_view3d.py 888class VIEW3D_PT_sculpt_symmetry(Panel, View3DPaintPanel): 889 bl_context = ".sculpt_mode" # dot on purpose (access from topbar) 890 bl_label = "Symmetry" 891 bl_options = {'DEFAULT_CLOSED'} 892 893 @classmethod 894 def poll(cls, context): 895 return ( 896 (context.sculpt_object and context.tool_settings.sculpt) and 897 # When used in the tool header, this is explicitly included next to the XYZ symmetry buttons. 898 (context.region.type != 'TOOL_HEADER') 899 ) 900 901 def draw(self, context): 902 layout = self.layout 903 layout.use_property_split = True 904 layout.use_property_decorate = False 905 906 sculpt = context.tool_settings.sculpt 907 908 row = layout.row(align=True, heading="Mirror") 909 mesh = context.object.data 910 row.prop(mesh, "use_mirror_x", text="X", toggle=True) 911 row.prop(mesh, "use_mirror_y", text="Y", toggle=True) 912 row.prop(mesh, "use_mirror_z", text="Z", toggle=True) 913 914 row = layout.row(align=True, heading="Lock") 915 row.prop(sculpt, "lock_x", text="X", toggle=True) 916 row.prop(sculpt, "lock_y", text="Y", toggle=True) 917 row.prop(sculpt, "lock_z", text="Z", toggle=True) 918 919 row = layout.row(align=True, heading="Tiling") 920 row.prop(sculpt, "tile_x", text="X", toggle=True) 921 row.prop(sculpt, "tile_y", text="Y", toggle=True) 922 row.prop(sculpt, "tile_z", text="Z", toggle=True) 923 924 layout.prop(sculpt, "use_symmetry_feather", text="Feather") 925 layout.prop(sculpt, "radial_symmetry", text="Radial") 926 layout.prop(sculpt, "tile_offset", text="Tile Offset") 927 928 layout.separator() 929 930 layout.prop(sculpt, "symmetrize_direction") 931 layout.operator("sculpt.symmetrize") 932 933 934class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel): 935 bl_space_type = 'TOPBAR' 936 bl_region_type = 'HEADER' 937 bl_label = "Symmetry" 938 939 draw = VIEW3D_PT_sculpt_symmetry.draw 940 941 942# ********** default tools for weight-paint **************** 943 944 945# TODO, move to space_view3d.py 946class VIEW3D_PT_tools_weightpaint_symmetry(Panel, View3DPaintPanel): 947 bl_context = ".weightpaint" 948 bl_options = {'DEFAULT_CLOSED'} 949 bl_label = "Symmetry" 950 951 @classmethod 952 def poll(cls, context): 953 # When used in the tool header, this is explicitly included next to the XYZ symmetry buttons. 954 return (context.region.type != 'TOOL_HEADER') 955 956 def draw(self, context): 957 layout = self.layout 958 tool_settings = context.tool_settings 959 wpaint = tool_settings.weight_paint 960 draw_vpaint_symmetry(layout, wpaint, context.object.data) 961 962 col = layout.column() 963 row = col.row(align=True) 964 row.prop(context.object.data, 'use_mirror_vertex_group_x') 965 966 967class VIEW3D_PT_tools_weightpaint_symmetry_for_topbar(Panel): 968 bl_space_type = 'TOPBAR' 969 bl_region_type = 'HEADER' 970 bl_label = "Symmetry" 971 972 draw = VIEW3D_PT_tools_weightpaint_symmetry.draw 973 974 975# TODO, move to space_view3d.py 976class VIEW3D_PT_tools_weightpaint_options(Panel, View3DPaintPanel): 977 bl_context = ".weightpaint" 978 bl_label = "Options" 979 bl_options = {'DEFAULT_CLOSED'} 980 981 def draw(self, context): 982 layout = self.layout 983 984 layout.use_property_split = True 985 layout.use_property_decorate = False 986 987 tool_settings = context.tool_settings 988 wpaint = tool_settings.weight_paint 989 990 col = layout.column() 991 992 col.prop(tool_settings, "use_auto_normalize", text="Auto Normalize") 993 col.prop(tool_settings, "use_lock_relative", text="Lock-Relative") 994 col.prop(tool_settings, "use_multipaint", text="Multi-Paint") 995 996 col.prop(wpaint, "use_group_restrict") 997 998 obj = context.weight_paint_object 999 if obj.type == 'MESH': 1000 mesh = obj.data 1001 col.prop(mesh, "use_mirror_x") 1002 row = col.row() 1003 row.active = mesh.use_mirror_x 1004 row.prop(mesh, "use_mirror_topology") 1005 1006 1007# ********** default tools for vertex-paint **************** 1008 1009 1010# TODO, move to space_view3d.py 1011class VIEW3D_PT_tools_vertexpaint_options(Panel, View3DPaintPanel): 1012 bl_context = ".vertexpaint" # dot on purpose (access from topbar) 1013 bl_label = "Options" 1014 bl_options = {'DEFAULT_CLOSED'} 1015 1016 @classmethod 1017 def poll(self, _context): 1018 # This is currently unused, since there aren't any Vertex Paint mode specific options. 1019 return False 1020 1021 def draw(self, _context): 1022 layout = self.layout 1023 layout.use_property_split = True 1024 layout.use_property_decorate = False 1025 1026 1027# TODO, move to space_view3d.py 1028class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel): 1029 bl_context = ".vertexpaint" # dot on purpose (access from topbar) 1030 bl_options = {'DEFAULT_CLOSED'} 1031 bl_label = "Symmetry" 1032 1033 @classmethod 1034 def poll(cls, context): 1035 # When used in the tool header, this is explicitly included next to the XYZ symmetry buttons. 1036 return (context.region.type != 'TOOL_HEADER') 1037 1038 def draw(self, context): 1039 layout = self.layout 1040 tool_settings = context.tool_settings 1041 vpaint = tool_settings.vertex_paint 1042 draw_vpaint_symmetry(layout, vpaint, context.object.data) 1043 1044 1045class VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar(Panel): 1046 bl_space_type = 'TOPBAR' 1047 bl_region_type = 'HEADER' 1048 bl_label = "Symmetry" 1049 1050 draw = VIEW3D_PT_tools_vertexpaint_symmetry.draw 1051 1052 1053# ********** default tools for texture-paint **************** 1054 1055 1056# TODO, move to space_view3d.py 1057class VIEW3D_PT_tools_imagepaint_options_external(Panel, View3DPaintPanel): 1058 bl_context = ".imagepaint" # dot on purpose (access from topbar) 1059 bl_label = "External" 1060 bl_parent_id = "VIEW3D_PT_tools_imagepaint_options" 1061 bl_options = {'DEFAULT_CLOSED'} 1062 1063 def draw(self, context): 1064 layout = self.layout 1065 layout.use_property_split = True 1066 layout.use_property_decorate = False 1067 1068 tool_settings = context.tool_settings 1069 ipaint = tool_settings.image_paint 1070 1071 layout.prop(ipaint, "screen_grab_size", text="Screen Grab Size") 1072 1073 layout.separator() 1074 1075 flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) 1076 col = flow.column() 1077 col.operator("image.project_edit", text="Quick Edit") 1078 col = flow.column() 1079 col.operator("image.project_apply", text="Apply") 1080 col = flow.column() 1081 col.operator("paint.project_image", text="Apply Camera Image") 1082 1083 1084# TODO, move to space_view3d.py 1085class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel): 1086 bl_context = ".imagepaint" # dot on purpose (access from topbar) 1087 bl_label = "Symmetry" 1088 bl_options = {'DEFAULT_CLOSED'} 1089 1090 @classmethod 1091 def poll(cls, context): 1092 # When used in the tool header, this is explicitly included next to the XYZ symmetry buttons. 1093 return (context.region.type != 'TOOL_HEADER') 1094 1095 def draw(self, context): 1096 layout = self.layout 1097 1098 split = layout.split() 1099 1100 col = split.column() 1101 col.alignment = 'RIGHT' 1102 col.label(text="Mirror") 1103 1104 col = split.column() 1105 1106 row = col.row(align=True) 1107 mesh = context.object.data 1108 row.prop(mesh, "use_mirror_x", text="X", toggle=True) 1109 row.prop(mesh, "use_mirror_y", text="Y", toggle=True) 1110 row.prop(mesh, "use_mirror_z", text="Z", toggle=True) 1111 1112 1113# TODO, move to space_view3d.py 1114class VIEW3D_PT_tools_imagepaint_options(View3DPaintPanel, Panel): 1115 bl_context = ".imagepaint" # dot on purpose (access from topbar) 1116 bl_label = "Options" 1117 bl_options = {'DEFAULT_CLOSED'} 1118 1119 @classmethod 1120 def poll(cls, context): 1121 brush = context.tool_settings.image_paint.brush 1122 return (brush is not None) 1123 1124 def draw(self, context): 1125 layout = self.layout 1126 1127 layout.use_property_split = True 1128 layout.use_property_decorate = False 1129 1130 tool_settings = context.tool_settings 1131 ipaint = tool_settings.image_paint 1132 1133 layout.prop(ipaint, "seam_bleed") 1134 layout.prop(ipaint, "dither", slider=True) 1135 1136 col = layout.column() 1137 col.prop(ipaint, "use_occlude") 1138 col.prop(ipaint, "use_backface_culling", text="Backface Culling") 1139 1140 1141class VIEW3D_PT_tools_imagepaint_options_cavity(View3DPaintPanel, Panel): 1142 bl_context = ".imagepaint" # dot on purpose (access from topbar) 1143 bl_label = "Cavity Mask" 1144 bl_parent_id = "VIEW3D_PT_mask" 1145 bl_options = {'DEFAULT_CLOSED'} 1146 1147 def draw_header(self, context): 1148 tool_settings = context.tool_settings 1149 ipaint = tool_settings.image_paint 1150 1151 self.layout.prop(ipaint, "use_cavity", text="") 1152 1153 def draw(self, context): 1154 layout = self.layout 1155 1156 tool_settings = context.tool_settings 1157 ipaint = tool_settings.image_paint 1158 1159 layout.active = ipaint.use_cavity 1160 1161 layout.template_curve_mapping(ipaint, "cavity_curve", brush=True, 1162 use_negative_slope=True) 1163 1164 1165# TODO, move to space_view3d.py 1166class VIEW3D_PT_imagepaint_options(View3DPaintPanel): 1167 bl_label = "Options" 1168 1169 @classmethod 1170 def poll(cls, _context): 1171 # This is currently unused, since there aren't any Vertex Paint mode specific options. 1172 return False 1173 # return (context.image_paint_object and context.tool_settings.image_paint) 1174 1175 def draw(self, _context): 1176 layout = self.layout 1177 layout.use_property_split = True 1178 layout.use_property_decorate = False 1179 1180 1181class VIEW3D_MT_tools_projectpaint_stencil(Menu): 1182 bl_label = "Mask Layer" 1183 1184 def draw(self, context): 1185 layout = self.layout 1186 for i, uv_layer in enumerate(context.active_object.data.uv_layers): 1187 props = layout.operator("wm.context_set_int", text=uv_layer.name, translate=False) 1188 props.data_path = "active_object.data.uv_layer_stencil_index" 1189 props.value = i 1190 1191 1192# TODO, move to space_view3d.py 1193class VIEW3D_PT_tools_particlemode_options(View3DPanel, Panel): 1194 """Default tools for particle mode""" 1195 bl_category = "Tool" 1196 bl_context = ".particlemode" 1197 bl_label = "Options" 1198 bl_options = {'DEFAULT_CLOSED'} 1199 1200 def draw(self, context): 1201 layout = self.layout 1202 1203 layout.use_property_split = True 1204 layout.use_property_decorate = False # No animation. 1205 1206 pe = context.tool_settings.particle_edit 1207 ob = pe.object 1208 1209 layout.prop(pe, "type", text="Editing Type") 1210 1211 ptcache = None 1212 1213 if pe.type == 'PARTICLES': 1214 if ob.particle_systems: 1215 if len(ob.particle_systems) > 1: 1216 layout.template_list("UI_UL_list", "particle_systems", ob, "particle_systems", 1217 ob.particle_systems, "active_index", rows=2, maxrows=3) 1218 1219 ptcache = ob.particle_systems.active.point_cache 1220 else: 1221 for md in ob.modifiers: 1222 if md.type == pe.type: 1223 ptcache = md.point_cache 1224 1225 if ptcache and len(ptcache.point_caches) > 1: 1226 layout.template_list("UI_UL_list", "particles_point_caches", ptcache, "point_caches", 1227 ptcache.point_caches, "active_index", rows=2, maxrows=3) 1228 1229 if not pe.is_editable: 1230 layout.label(text="Point cache must be baked") 1231 layout.label(text="in memory to enable editing!") 1232 1233 col = layout.column(align=True) 1234 col.active = pe.is_editable 1235 col.prop(ob.data, "use_mirror_x") 1236 if pe.tool == 'ADD': 1237 col.prop(ob.data, "use_mirror_topology") 1238 col.separator() 1239 col.prop(pe, "use_preserve_length", text="Preserve Strand Lengths") 1240 col.prop(pe, "use_preserve_root", text="Preserve Root Positions") 1241 if not pe.is_hair: 1242 col.prop(pe, "use_auto_velocity", text="Auto-Velocity") 1243 1244 1245class VIEW3D_PT_tools_particlemode_options_shapecut(View3DPanel, Panel): 1246 """Default tools for particle mode""" 1247 bl_category = "Tool" 1248 bl_parent_id = "VIEW3D_PT_tools_particlemode_options" 1249 bl_label = "Cut Particles to Shape" 1250 bl_options = {'DEFAULT_CLOSED'} 1251 1252 def draw(self, context): 1253 layout = self.layout 1254 1255 layout.use_property_split = True 1256 layout.use_property_decorate = False # No animation. 1257 1258 pe = context.tool_settings.particle_edit 1259 1260 layout.prop(pe, "shape_object") 1261 layout.operator("particle.shape_cut", text="Cut") 1262 1263 1264class VIEW3D_PT_tools_particlemode_options_display(View3DPanel, Panel): 1265 """Default tools for particle mode""" 1266 bl_category = "Tool" 1267 bl_parent_id = "VIEW3D_PT_tools_particlemode_options" 1268 bl_label = "Viewport Display" 1269 1270 def draw(self, context): 1271 layout = self.layout 1272 1273 layout.use_property_split = True 1274 layout.use_property_decorate = False # No animation. 1275 1276 pe = context.tool_settings.particle_edit 1277 1278 col = layout.column() 1279 col.active = pe.is_editable 1280 col.prop(pe, "display_step", text="Path Steps") 1281 if pe.is_hair: 1282 col.prop(pe, "show_particles", text="Children") 1283 else: 1284 if pe.type == 'PARTICLES': 1285 col.prop(pe, "show_particles", text="Particles") 1286 col.prop(pe, "use_fade_time") 1287 sub = col.row(align=True) 1288 sub.active = pe.use_fade_time 1289 sub.prop(pe, "fade_frames", slider=True) 1290 1291 1292# ********** grease pencil object tool panels **************** 1293 1294# Grease Pencil drawing brushes 1295 1296 1297class GreasePencilPaintPanel: 1298 bl_context = ".greasepencil_paint" 1299 bl_category = "Tool" 1300 1301 @classmethod 1302 def poll(cls, context): 1303 if context.space_data.type in {'VIEW_3D', 'PROPERTIES'}: 1304 if context.gpencil_data is None: 1305 return False 1306 1307 gpd = context.gpencil_data 1308 return bool(gpd.is_stroke_paint_mode) 1309 else: 1310 return True 1311 1312 1313class VIEW3D_PT_tools_grease_pencil_brush_select(Panel, View3DPanel, GreasePencilPaintPanel): 1314 bl_label = "Brushes" 1315 1316 def draw(self, context): 1317 layout = self.layout 1318 layout.use_property_split = True 1319 layout.use_property_decorate = False 1320 1321 tool_settings = context.scene.tool_settings 1322 gpencil_paint = tool_settings.gpencil_paint 1323 1324 row = layout.row() 1325 row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8) 1326 1327 col = row.column() 1328 col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="") 1329 1330 if context.mode == 'PAINT_GPENCIL': 1331 brush = tool_settings.gpencil_paint.brush 1332 if brush is not None: 1333 gp_settings = brush.gpencil_settings 1334 1335 col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="") 1336 1337 if brush.use_custom_icon: 1338 layout.row().prop(brush, "icon_filepath", text="") 1339 1340 1341class VIEW3D_PT_tools_grease_pencil_brush_settings(Panel, View3DPanel, GreasePencilPaintPanel): 1342 bl_label = "Brush Settings" 1343 bl_options = {'DEFAULT_CLOSED'} 1344 1345 # What is the point of brush presets? Seems to serve the exact same purpose as brushes themselves?? 1346 def draw_header_preset(self, _context): 1347 VIEW3D_PT_gpencil_brush_presets.draw_panel_header(self.layout) 1348 1349 def draw(self, context): 1350 layout = self.layout 1351 layout.use_property_split = True 1352 layout.use_property_decorate = False 1353 1354 tool_settings = context.scene.tool_settings 1355 gpencil_paint = tool_settings.gpencil_paint 1356 1357 brush = gpencil_paint.brush 1358 1359 if brush is not None: 1360 gp_settings = brush.gpencil_settings 1361 1362 if brush.gpencil_tool in {'DRAW', 'FILL'}: 1363 row = layout.row(align=True) 1364 row_mat = row.row() 1365 if gp_settings.use_material_pin: 1366 row_mat.template_ID(gp_settings, "material", live_icon=True) 1367 else: 1368 row_mat.template_ID(context.active_object, "active_material", live_icon=True) 1369 row_mat.enabled = False # will otherwise allow to change material in active slot 1370 1371 row.prop(gp_settings, "use_material_pin", text="") 1372 1373 if not self.is_popover: 1374 from bl_ui.properties_paint_common import ( 1375 brush_basic_gpencil_paint_settings, 1376 ) 1377 brush_basic_gpencil_paint_settings(layout, context, brush, compact=False) 1378 1379 1380class VIEW3D_PT_tools_grease_pencil_brush_advanced(View3DPanel, Panel): 1381 bl_context = ".greasepencil_paint" 1382 bl_label = "Advanced" 1383 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings' 1384 bl_category = "Tool" 1385 bl_options = {'DEFAULT_CLOSED'} 1386 bl_ui_units_x = 11 1387 1388 @classmethod 1389 def poll(cls, context): 1390 brush = context.tool_settings.gpencil_paint.brush 1391 return brush is not None and brush.gpencil_tool not in {'ERASE', 'TINT'} 1392 1393 def draw(self, context): 1394 layout = self.layout 1395 layout.use_property_split = True 1396 layout.use_property_decorate = False 1397 1398 tool_settings = context.scene.tool_settings 1399 gpencil_paint = tool_settings.gpencil_paint 1400 brush = gpencil_paint.brush 1401 gp_settings = brush.gpencil_settings 1402 1403 col = layout.column(align=True) 1404 if brush is not None: 1405 if brush.gpencil_tool != 'FILL': 1406 col.prop(gp_settings, "input_samples") 1407 col.separator() 1408 1409 col.prop(gp_settings, "active_smooth_factor") 1410 col.separator() 1411 1412 col.prop(gp_settings, "angle", slider=True) 1413 col.prop(gp_settings, "angle_factor", text="Factor", slider=True) 1414 1415 ob = context.object 1416 ma = None 1417 if ob and brush.gpencil_settings.use_material_pin is False: 1418 ma = ob.active_material 1419 elif brush.gpencil_settings.material: 1420 ma = brush.gpencil_settings.material 1421 1422 col.separator() 1423 col.prop(gp_settings, "hardness", slider=True) 1424 subcol = col.column(align=True) 1425 if ma and ma.grease_pencil.mode == 'LINE': 1426 subcol.enabled = False 1427 subcol.prop(gp_settings, "aspect") 1428 1429 elif brush.gpencil_tool == 'FILL': 1430 row = col.row(align=True) 1431 row.prop(gp_settings, "fill_draw_mode", text="Boundary") 1432 row.prop(gp_settings, "show_fill_boundary", text="", icon='GRID') 1433 1434 col.separator() 1435 row = col.row(align=True) 1436 row.prop(gp_settings, "fill_layer_mode", text="Layers") 1437 1438 col.separator() 1439 col.prop(gp_settings, "fill_factor", text="Resolution") 1440 if gp_settings.fill_draw_mode != 'STROKE': 1441 col = layout.column(align=False, heading="Ignore Transparent") 1442 col.use_property_decorate = False 1443 row = col.row(align=True) 1444 sub = row.row(align=True) 1445 sub.prop(gp_settings, "show_fill", text="") 1446 sub = sub.row(align=True) 1447 sub.active = gp_settings.show_fill 1448 sub.prop(gp_settings, "fill_threshold", text="") 1449 1450 1451class VIEW3D_PT_tools_grease_pencil_brush_stroke(Panel, View3DPanel): 1452 bl_context = ".greasepencil_paint" 1453 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings' 1454 bl_label = "Stroke" 1455 bl_category = "Tool" 1456 bl_options = {'DEFAULT_CLOSED'} 1457 bl_ui_units_x = 12 1458 1459 @classmethod 1460 def poll(cls, context): 1461 brush = context.tool_settings.gpencil_paint.brush 1462 return brush is not None and brush.gpencil_tool == 'DRAW' 1463 1464 def draw(self, context): 1465 layout = self.layout 1466 1467 1468class VIEW3D_PT_tools_grease_pencil_brush_stabilizer(Panel, View3DPanel): 1469 bl_context = ".greasepencil_paint" 1470 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_stroke' 1471 bl_label = "Stabilize Stroke" 1472 bl_category = "Tool" 1473 bl_options = {'DEFAULT_CLOSED'} 1474 1475 @classmethod 1476 def poll(cls, context): 1477 brush = context.tool_settings.gpencil_paint.brush 1478 return brush is not None and brush.gpencil_tool == 'DRAW' 1479 1480 def draw_header(self, context): 1481 if self.is_popover: 1482 return 1483 1484 brush = context.tool_settings.gpencil_paint.brush 1485 gp_settings = brush.gpencil_settings 1486 self.layout.prop(gp_settings, "use_settings_stabilizer", text="") 1487 1488 def draw(self, context): 1489 layout = self.layout 1490 layout.use_property_split = True 1491 layout.use_property_decorate = False 1492 1493 brush = context.tool_settings.gpencil_paint.brush 1494 gp_settings = brush.gpencil_settings 1495 1496 if self.is_popover: 1497 row = layout.row() 1498 row.prop(gp_settings, "use_settings_stabilizer", text="") 1499 row.label(text=self.bl_label) 1500 1501 col = layout.column() 1502 col.active = gp_settings.use_settings_stabilizer 1503 1504 col.prop(brush, "smooth_stroke_radius", text="Radius", slider=True) 1505 col.prop(brush, "smooth_stroke_factor", text="Factor", slider=True) 1506 1507 1508class VIEW3D_PT_tools_grease_pencil_brush_post_processing(View3DPanel, Panel): 1509 bl_context = ".greasepencil_paint" 1510 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_stroke' 1511 bl_label = "Post-Processing" 1512 bl_category = "Tool" 1513 bl_options = {'DEFAULT_CLOSED'} 1514 1515 @classmethod 1516 def poll(cls, context): 1517 brush = context.tool_settings.gpencil_paint.brush 1518 return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'} 1519 1520 def draw_header(self, context): 1521 if self.is_popover: 1522 return 1523 1524 brush = context.tool_settings.gpencil_paint.brush 1525 gp_settings = brush.gpencil_settings 1526 self.layout.prop(gp_settings, "use_settings_postprocess", text="") 1527 1528 def draw(self, context): 1529 layout = self.layout 1530 layout.use_property_split = True 1531 layout.use_property_decorate = False 1532 1533 brush = context.tool_settings.gpencil_paint.brush 1534 gp_settings = brush.gpencil_settings 1535 1536 if self.is_popover: 1537 row = layout.row() 1538 row.prop(gp_settings, "use_settings_postprocess", text="") 1539 row.label(text=self.bl_label) 1540 1541 col = layout.column() 1542 col.active = gp_settings.use_settings_postprocess 1543 1544 col1 = col.column(align=True) 1545 col1.prop(gp_settings, "pen_smooth_factor") 1546 col1.prop(gp_settings, "pen_smooth_steps") 1547 1548 col1 = col.column(align=True) 1549 col1.prop(gp_settings, "pen_subdivision_steps") 1550 1551 col1 = col.column(align=True) 1552 col1.prop(gp_settings, "simplify_factor") 1553 1554 col1 = col.column(align=True) 1555 col1.prop(gp_settings, "use_trim") 1556 1557 1558class VIEW3D_PT_tools_grease_pencil_brush_random(View3DPanel, Panel): 1559 bl_context = ".greasepencil_paint" 1560 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_stroke' 1561 bl_label = "Randomize" 1562 bl_category = "Tool" 1563 bl_options = {'DEFAULT_CLOSED'} 1564 1565 @classmethod 1566 def poll(cls, context): 1567 brush = context.tool_settings.gpencil_paint.brush 1568 return brush is not None and brush.gpencil_tool not in {'ERASE', 'FILL', 'TINT'} 1569 1570 def draw_header(self, context): 1571 if self.is_popover: 1572 return 1573 1574 brush = context.tool_settings.gpencil_paint.brush 1575 gp_settings = brush.gpencil_settings 1576 self.layout.prop(gp_settings, "use_settings_random", text="") 1577 1578 def draw(self, context): 1579 layout = self.layout 1580 layout.use_property_split = True 1581 layout.use_property_decorate = False 1582 1583 tool_settings = context.tool_settings 1584 brush = tool_settings.gpencil_paint.brush 1585 mode = tool_settings.gpencil_paint.color_mode 1586 gp_settings = brush.gpencil_settings 1587 1588 if self.is_popover: 1589 row = layout.row() 1590 row.prop(gp_settings, "use_settings_random", text="") 1591 row.label(text=self.bl_label) 1592 1593 col = layout.column() 1594 col.enabled = gp_settings.use_settings_random 1595 1596 row = col.row(align=True) 1597 row.prop(gp_settings, "random_pressure", text="Radius", slider=True) 1598 row.prop(gp_settings, "use_stroke_random_radius", text="", icon='GP_SELECT_STROKES') 1599 row.prop(gp_settings, "use_random_press_radius", text="", icon='STYLUS_PRESSURE') 1600 if gp_settings.use_random_press_radius and self.is_popover is False: 1601 col.template_curve_mapping(gp_settings, "curve_random_pressure", brush=True, 1602 use_negative_slope=True) 1603 1604 row = col.row(align=True) 1605 row.prop(gp_settings, "random_strength", text="Strength", slider=True) 1606 row.prop(gp_settings, "use_stroke_random_strength", text="", icon='GP_SELECT_STROKES') 1607 row.prop(gp_settings, "use_random_press_strength", text="", icon='STYLUS_PRESSURE') 1608 if gp_settings.use_random_press_strength and self.is_popover is False: 1609 col.template_curve_mapping(gp_settings, "curve_random_strength", brush=True, 1610 use_negative_slope=True) 1611 1612 row = col.row(align=True) 1613 row.prop(gp_settings, "uv_random", text="UV", slider=True) 1614 row.prop(gp_settings, "use_stroke_random_uv", text="", icon='GP_SELECT_STROKES') 1615 row.prop(gp_settings, "use_random_press_uv", text="", icon='STYLUS_PRESSURE') 1616 if gp_settings.use_random_press_uv and self.is_popover is False: 1617 col.template_curve_mapping(gp_settings, "curve_random_uv", brush=True, 1618 use_negative_slope=True) 1619 1620 col.separator() 1621 1622 col1 = col.column(align=True) 1623 col1.enabled = mode == 'VERTEXCOLOR' and gp_settings.use_settings_random 1624 row = col1.row(align=True) 1625 row.prop(gp_settings, "random_hue_factor", slider=True) 1626 row.prop(gp_settings, "use_stroke_random_hue", text="", icon='GP_SELECT_STROKES') 1627 row.prop(gp_settings, "use_random_press_hue", text="", icon='STYLUS_PRESSURE') 1628 if gp_settings.use_random_press_hue and self.is_popover is False: 1629 col1.template_curve_mapping(gp_settings, "curve_random_hue", brush=True, 1630 use_negative_slope=True) 1631 1632 row = col1.row(align=True) 1633 row.prop(gp_settings, "random_saturation_factor", slider=True) 1634 row.prop(gp_settings, "use_stroke_random_sat", text="", icon='GP_SELECT_STROKES') 1635 row.prop(gp_settings, "use_random_press_sat", text="", icon='STYLUS_PRESSURE') 1636 if gp_settings.use_random_press_sat and self.is_popover is False: 1637 col1.template_curve_mapping(gp_settings, "curve_random_saturation", brush=True, 1638 use_negative_slope=True) 1639 1640 row = col1.row(align=True) 1641 row.prop(gp_settings, "random_value_factor", slider=True) 1642 row.prop(gp_settings, "use_stroke_random_val", text="", icon='GP_SELECT_STROKES') 1643 row.prop(gp_settings, "use_random_press_val", text="", icon='STYLUS_PRESSURE') 1644 if gp_settings.use_random_press_val and self.is_popover is False: 1645 col1.template_curve_mapping(gp_settings, "curve_random_value", brush=True, 1646 use_negative_slope=True) 1647 1648 col.separator() 1649 1650 row = col.row(align=True) 1651 row.prop(gp_settings, "pen_jitter", slider=True) 1652 row.prop(gp_settings, "use_jitter_pressure", text="", icon='STYLUS_PRESSURE') 1653 if gp_settings.use_jitter_pressure and self.is_popover is False: 1654 col.template_curve_mapping(gp_settings, "curve_jitter", brush=True, 1655 use_negative_slope=True) 1656 1657 1658class VIEW3D_PT_tools_grease_pencil_brush_paint_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel): 1659 bl_context = ".greasepencil_paint" 1660 bl_label = "Falloff" 1661 bl_options = {'DEFAULT_CLOSED'} 1662 1663 @classmethod 1664 def poll(cls, context): 1665 ts = context.tool_settings 1666 settings = ts.gpencil_paint 1667 brush = settings.brush 1668 if brush is None: 1669 return False 1670 1671 tool = brush.gpencil_tool 1672 1673 return (settings and settings.brush and settings.brush.curve and tool == 'TINT') 1674 1675 1676# Grease Pencil stroke interpolation tools 1677class VIEW3D_PT_tools_grease_pencil_interpolate(Panel): 1678 bl_space_type = 'VIEW_3D' 1679 bl_region_type = 'HEADER' 1680 bl_label = "Interpolate" 1681 1682 @classmethod 1683 def poll(cls, context): 1684 if context.gpencil_data is None: 1685 return False 1686 1687 gpd = context.gpencil_data 1688 return bool(context.editable_gpencil_strokes) and bool(gpd.use_stroke_edit_mode) 1689 1690 def draw(self, context): 1691 layout = self.layout 1692 settings = context.tool_settings.gpencil_interpolate 1693 1694 col = layout.column(align=True) 1695 col.label(text="Interpolate Strokes") 1696 col.operator("gpencil.interpolate", text="Interpolate") 1697 col.operator("gpencil.interpolate_sequence", text="Sequence") 1698 col.operator("gpencil.interpolate_reverse", text="Remove Breakdowns") 1699 1700 col = layout.column(align=True) 1701 col.label(text="Options:") 1702 col.prop(settings, "interpolate_all_layers") 1703 col.prop(settings, "interpolate_selected_only") 1704 1705 col = layout.column(align=True) 1706 col.label(text="Sequence Options:") 1707 col.prop(settings, "step") 1708 col.prop(settings, "type") 1709 if settings.type == 'CUSTOM': 1710 # TODO: Options for loading/saving curve presets? 1711 col.template_curve_mapping(settings, "interpolation_curve", brush=True, 1712 use_negative_slope=True) 1713 elif settings.type != 'LINEAR': 1714 col.prop(settings, "easing") 1715 1716 if settings.type == 'BACK': 1717 layout.prop(settings, "back") 1718 elif settings.type == 'ELASTIC': 1719 sub = layout.column(align=True) 1720 sub.prop(settings, "amplitude") 1721 sub.prop(settings, "period") 1722 1723 1724# Grease Pencil stroke sculpting tools 1725class GreasePencilSculptPanel: 1726 bl_context = ".greasepencil_sculpt" 1727 bl_category = "Tool" 1728 1729 @classmethod 1730 def poll(cls, context): 1731 if context.space_data.type in {'VIEW_3D', 'PROPERTIES'}: 1732 if context.gpencil_data is None: 1733 return False 1734 1735 gpd = context.gpencil_data 1736 return bool(gpd.is_stroke_sculpt_mode) 1737 else: 1738 return True 1739 1740 1741class VIEW3D_PT_tools_grease_pencil_sculpt_select(Panel, View3DPanel, GreasePencilSculptPanel): 1742 bl_label = "Brushes" 1743 1744 def draw(self, context): 1745 layout = self.layout 1746 layout.use_property_split = True 1747 layout.use_property_decorate = False 1748 1749 tool_settings = context.scene.tool_settings 1750 gpencil_paint = tool_settings.gpencil_sculpt_paint 1751 1752 row = layout.row() 1753 row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8) 1754 1755 col = row.column() 1756 col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="") 1757 1758 if context.mode == 'SCULPT_GPENCIL': 1759 brush = tool_settings.gpencil_sculpt_paint.brush 1760 if brush is not None: 1761 col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="") 1762 1763 if(brush.use_custom_icon): 1764 layout.row().prop(brush, "icon_filepath", text="") 1765 1766 1767class VIEW3D_PT_tools_grease_pencil_sculpt_settings(Panel, View3DPanel, GreasePencilSculptPanel): 1768 bl_label = "Brush Settings" 1769 1770 def draw(self, context): 1771 layout = self.layout 1772 layout.use_property_split = True 1773 layout.use_property_decorate = False 1774 1775 tool_settings = context.scene.tool_settings 1776 settings = tool_settings.gpencil_sculpt_paint 1777 brush = settings.brush 1778 1779 if not self.is_popover: 1780 from bl_ui.properties_paint_common import ( 1781 brush_basic_gpencil_sculpt_settings, 1782 ) 1783 brush_basic_gpencil_sculpt_settings(layout, context, brush) 1784 1785 1786class VIEW3D_PT_tools_grease_pencil_brush_sculpt_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel): 1787 bl_context = ".greasepencil_sculpt" 1788 bl_label = "Falloff" 1789 bl_options = {'DEFAULT_CLOSED'} 1790 1791 @classmethod 1792 def poll(cls, context): 1793 ts = context.tool_settings 1794 settings = ts.gpencil_sculpt_paint 1795 return (settings and settings.brush and settings.brush.curve) 1796 1797 1798# Grease Pencil weight painting tools 1799class GreasePencilWeightPanel: 1800 bl_context = ".greasepencil_weight" 1801 bl_category = "Tool" 1802 1803 @classmethod 1804 def poll(cls, context): 1805 if context.space_data.type in {'VIEW_3D', 'PROPERTIES'}: 1806 if context.gpencil_data is None: 1807 return False 1808 1809 gpd = context.gpencil_data 1810 return bool(gpd.is_stroke_weight_mode) 1811 else: 1812 return True 1813 1814 1815class VIEW3D_PT_tools_grease_pencil_weight_paint_select(View3DPanel, Panel, GreasePencilWeightPanel): 1816 bl_label = "Brushes" 1817 1818 def draw(self, context): 1819 layout = self.layout 1820 layout.use_property_split = True 1821 layout.use_property_decorate = False 1822 1823 tool_settings = context.scene.tool_settings 1824 gpencil_paint = tool_settings.gpencil_weight_paint 1825 1826 row = layout.row() 1827 row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8) 1828 1829 col = row.column() 1830 col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="") 1831 1832 if context.mode == 'WEIGHT_GPENCIL': 1833 brush = tool_settings.gpencil_weight_paint.brush 1834 if brush is not None: 1835 col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="") 1836 1837 if(brush.use_custom_icon): 1838 layout.row().prop(brush, "icon_filepath", text="") 1839 1840 1841class VIEW3D_PT_tools_grease_pencil_weight_paint_settings(Panel, View3DPanel, GreasePencilWeightPanel): 1842 bl_label = "Brush Settings" 1843 1844 def draw(self, context): 1845 layout = self.layout 1846 layout.use_property_split = True 1847 layout.use_property_decorate = False 1848 1849 tool_settings = context.scene.tool_settings 1850 settings = tool_settings.gpencil_weight_paint 1851 brush = settings.brush 1852 1853 if not self.is_popover: 1854 from bl_ui.properties_paint_common import ( 1855 brush_basic_gpencil_weight_settings, 1856 ) 1857 brush_basic_gpencil_weight_settings(layout, context, brush) 1858 1859 1860class VIEW3D_PT_tools_grease_pencil_brush_weight_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel): 1861 bl_context = ".greasepencil_weight" 1862 bl_label = "Falloff" 1863 bl_options = {'DEFAULT_CLOSED'} 1864 1865 @classmethod 1866 def poll(cls, context): 1867 ts = context.tool_settings 1868 settings = ts.gpencil_weight_paint 1869 brush = settings.brush 1870 return (settings and settings.brush and settings.brush.curve) 1871 1872 1873# Grease Pencil vertex painting tools 1874class GreasePencilVertexPanel: 1875 bl_context = ".greasepencil_vertex" 1876 bl_category = "Tool" 1877 1878 @classmethod 1879 def poll(cls, context): 1880 if context.space_data.type in {'VIEW_3D', 'PROPERTIES'}: 1881 if context.gpencil_data is None: 1882 return False 1883 1884 gpd = context.gpencil_data 1885 return bool(gpd.is_stroke_vertex_mode) 1886 else: 1887 return True 1888 1889 1890class VIEW3D_PT_tools_grease_pencil_vertex_paint_select(View3DPanel, Panel, GreasePencilVertexPanel): 1891 bl_label = "Brushes" 1892 1893 def draw(self, context): 1894 layout = self.layout 1895 layout.use_property_split = True 1896 layout.use_property_decorate = False 1897 1898 tool_settings = context.scene.tool_settings 1899 gpencil_paint = tool_settings.gpencil_vertex_paint 1900 1901 row = layout.row() 1902 row.column().template_ID_preview(gpencil_paint, "brush", new="brush.add_gpencil", rows=3, cols=8) 1903 1904 col = row.column() 1905 col.menu("VIEW3D_MT_brush_gpencil_context_menu", icon='DOWNARROW_HLT', text="") 1906 1907 if context.mode == 'VERTEX_GPENCIL': 1908 brush = tool_settings.gpencil_vertex_paint.brush 1909 if brush is not None: 1910 col.prop(brush, "use_custom_icon", toggle=True, icon='FILE_IMAGE', text="") 1911 1912 if(brush.use_custom_icon): 1913 layout.row().prop(brush, "icon_filepath", text="") 1914 1915 1916class VIEW3D_PT_tools_grease_pencil_vertex_paint_settings(Panel, View3DPanel, GreasePencilVertexPanel): 1917 bl_label = "Brush Settings" 1918 1919 def draw(self, context): 1920 layout = self.layout 1921 layout.use_property_split = True 1922 layout.use_property_decorate = False 1923 1924 tool_settings = context.scene.tool_settings 1925 settings = tool_settings.gpencil_vertex_paint 1926 brush = settings.brush 1927 1928 if not self.is_popover: 1929 from bl_ui.properties_paint_common import ( 1930 brush_basic_gpencil_vertex_settings, 1931 ) 1932 brush_basic_gpencil_vertex_settings(layout, context, brush) 1933 1934 1935class VIEW3D_PT_tools_grease_pencil_brush_vertex_color(View3DPanel, Panel): 1936 bl_context = ".greasepencil_vertex" 1937 bl_label = "Color" 1938 bl_category = "Tool" 1939 1940 @classmethod 1941 def poll(cls, context): 1942 ob = context.object 1943 ts = context.tool_settings 1944 settings = ts.gpencil_vertex_paint 1945 brush = settings.brush 1946 1947 if ob is None or brush is None: 1948 return False 1949 1950 if context.region.type == 'TOOL_HEADER' or brush.gpencil_vertex_tool in {'BLUR', 'AVERAGE', 'SMEAR'}: 1951 return False 1952 1953 return True 1954 1955 def draw(self, context): 1956 layout = self.layout 1957 layout.use_property_split = True 1958 layout.use_property_decorate = False 1959 ts = context.tool_settings 1960 settings = ts.gpencil_vertex_paint 1961 brush = settings.brush 1962 gp_settings = brush.gpencil_settings 1963 1964 col = layout.column() 1965 1966 col.template_color_picker(brush, "color", value_slider=True) 1967 1968 sub_row = col.row(align=True) 1969 sub_row.prop(brush, "color", text="") 1970 sub_row.prop(brush, "secondary_color", text="") 1971 1972 sub_row.operator("gpencil.tint_flip", icon='FILE_REFRESH', text="") 1973 1974 1975class VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff(GreasePencilBrushFalloff, Panel, View3DPaintPanel): 1976 bl_context = ".greasepencil_vertex" 1977 bl_label = "Falloff" 1978 bl_options = {'DEFAULT_CLOSED'} 1979 1980 @classmethod 1981 def poll(cls, context): 1982 ts = context.tool_settings 1983 settings = ts.gpencil_vertex_paint 1984 return (settings and settings.brush and settings.brush.curve) 1985 1986 1987class VIEW3D_PT_tools_grease_pencil_brush_vertex_palette(View3DPanel, Panel): 1988 bl_context = ".greasepencil_vertex" 1989 bl_label = "Palette" 1990 bl_category = "Tool" 1991 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_vertex_color' 1992 1993 @classmethod 1994 def poll(cls, context): 1995 ob = context.object 1996 ts = context.tool_settings 1997 settings = ts.gpencil_vertex_paint 1998 brush = settings.brush 1999 2000 if ob is None or brush is None: 2001 return False 2002 2003 if brush.gpencil_vertex_tool in {'BLUR', 'AVERAGE', 'SMEAR'}: 2004 return False 2005 2006 return True 2007 2008 def draw(self, context): 2009 layout = self.layout 2010 layout.use_property_split = True 2011 layout.use_property_decorate = False 2012 ts = context.tool_settings 2013 settings = ts.gpencil_vertex_paint 2014 2015 col = layout.column() 2016 2017 row = col.row(align=True) 2018 row.template_ID(settings, "palette", new="palette.new") 2019 if settings.palette: 2020 col.template_palette(settings, "palette", color=True) 2021 2022 2023class VIEW3D_PT_tools_grease_pencil_brush_mixcolor(View3DPanel, Panel): 2024 bl_context = ".greasepencil_paint" 2025 bl_label = "Color" 2026 bl_category = "Tool" 2027 2028 @classmethod 2029 def poll(cls, context): 2030 ob = context.object 2031 ts = context.tool_settings 2032 settings = ts.gpencil_paint 2033 brush = settings.brush 2034 2035 if ob is None or brush is None: 2036 return False 2037 2038 if context.region.type == 'TOOL_HEADER': 2039 return False 2040 2041 if brush.gpencil_tool == 'TINT': 2042 return True 2043 2044 if brush.gpencil_tool not in {'DRAW', 'FILL'}: 2045 return False 2046 2047 return True 2048 2049 def draw(self, context): 2050 layout = self.layout 2051 ts = context.tool_settings 2052 settings = ts.gpencil_paint 2053 brush = settings.brush 2054 gp_settings = brush.gpencil_settings 2055 2056 if brush.gpencil_tool != 'TINT': 2057 row = layout.row() 2058 row.prop(settings, "color_mode", expand=True) 2059 2060 layout.use_property_split = True 2061 layout.use_property_decorate = False 2062 col = layout.column() 2063 col.enabled = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT' 2064 2065 col.template_color_picker(brush, "color", value_slider=True) 2066 2067 sub_row = col.row(align=True) 2068 sub_row.prop(brush, "color", text="") 2069 sub_row.prop(brush, "secondary_color", text="") 2070 2071 sub_row.operator("gpencil.tint_flip", icon='FILE_REFRESH', text="") 2072 2073 if brush.gpencil_tool in {'DRAW', 'FILL'}: 2074 col.prop(gp_settings, "vertex_mode", text="Mode") 2075 col.prop(gp_settings, "vertex_color_factor", slider=True, text="Mix Factor") 2076 2077 if brush.gpencil_tool == 'TINT': 2078 col.prop(gp_settings, "vertex_mode", text="Mode") 2079 2080 2081class VIEW3D_PT_tools_grease_pencil_brush_mix_palette(View3DPanel, Panel): 2082 bl_context = ".greasepencil_paint" 2083 bl_label = "Palette" 2084 bl_category = "Tool" 2085 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_mixcolor' 2086 2087 @classmethod 2088 def poll(cls, context): 2089 ob = context.object 2090 ts = context.tool_settings 2091 settings = ts.gpencil_paint 2092 brush = settings.brush 2093 2094 if ob is None or brush is None: 2095 return False 2096 2097 if brush.gpencil_tool == 'TINT': 2098 return True 2099 2100 if brush.gpencil_tool not in {'DRAW', 'FILL'}: 2101 return False 2102 2103 return True 2104 2105 def draw(self, context): 2106 layout = self.layout 2107 layout.use_property_split = True 2108 layout.use_property_decorate = False 2109 ts = context.tool_settings 2110 settings = ts.gpencil_paint 2111 brush = settings.brush 2112 2113 col = layout.column() 2114 col.enabled = settings.color_mode == 'VERTEXCOLOR' or brush.gpencil_tool == 'TINT' 2115 2116 row = col.row(align=True) 2117 row.template_ID(settings, "palette", new="palette.new") 2118 if settings.palette: 2119 col.template_palette(settings, "palette", color=True) 2120 2121 2122class VIEW3D_PT_tools_grease_pencil_sculpt_options(GreasePencilSculptOptionsPanel, Panel, View3DPanel): 2123 bl_context = ".greasepencil_sculpt" 2124 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_sculpt_settings' 2125 bl_category = "Tool" 2126 bl_label = "Sculpt Strokes" 2127 2128 2129# Grease Pencil Brush Appearance (one for each mode) 2130class VIEW3D_PT_tools_grease_pencil_paint_appearance(GreasePencilDisplayPanel, Panel, View3DPanel): 2131 bl_context = ".greasepencil_paint" 2132 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_brush_settings' 2133 bl_label = "Cursor" 2134 bl_category = "Tool" 2135 bl_ui_units_x = 15 2136 2137 2138class VIEW3D_PT_tools_grease_pencil_sculpt_appearance(GreasePencilDisplayPanel, Panel, View3DPanel): 2139 bl_context = ".greasepencil_sculpt" 2140 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_sculpt_settings' 2141 bl_label = "Cursor" 2142 bl_category = "Tool" 2143 2144 2145class VIEW3D_PT_tools_grease_pencil_weight_appearance(GreasePencilDisplayPanel, Panel, View3DPanel): 2146 bl_context = ".greasepencil_weight" 2147 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_weight_paint_settings' 2148 bl_category = "Tool" 2149 bl_label = "Cursor" 2150 2151 2152class VIEW3D_PT_tools_grease_pencil_vertex_appearance(GreasePencilDisplayPanel, Panel, View3DPanel): 2153 bl_context = ".greasepencil_vertex" 2154 bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_vertex_paint_settings' 2155 bl_category = "Tool" 2156 bl_label = "Cursor" 2157 2158 2159class VIEW3D_PT_gpencil_brush_presets(Panel, PresetPanel): 2160 """Brush settings""" 2161 bl_label = "Brush Presets" 2162 preset_subdir = "gpencil_brush" 2163 preset_operator = "script.execute_preset" 2164 preset_add_operator = "scene.gpencil_brush_preset_add" 2165 2166 2167classes = ( 2168 VIEW3D_MT_brush_context_menu, 2169 VIEW3D_MT_brush_gpencil_context_menu, 2170 VIEW3D_MT_brush_context_menu_paint_modes, 2171 VIEW3D_PT_tools_object_options, 2172 VIEW3D_PT_tools_object_options_transform, 2173 VIEW3D_PT_tools_meshedit_options, 2174 VIEW3D_PT_tools_meshedit_options_automerge, 2175 VIEW3D_PT_tools_armatureedit_options, 2176 VIEW3D_PT_tools_posemode_options, 2177 2178 VIEW3D_PT_slots_projectpaint, 2179 VIEW3D_PT_tools_brush_select, 2180 VIEW3D_PT_tools_brush_settings, 2181 VIEW3D_PT_tools_brush_color, 2182 VIEW3D_PT_tools_brush_swatches, 2183 VIEW3D_PT_tools_brush_settings_advanced, 2184 VIEW3D_PT_tools_brush_clone, 2185 TEXTURE_UL_texpaintslots, 2186 VIEW3D_MT_tools_projectpaint_uvlayer, 2187 VIEW3D_PT_tools_brush_texture, 2188 VIEW3D_PT_tools_mask_texture, 2189 VIEW3D_PT_tools_brush_stroke, 2190 VIEW3D_PT_tools_brush_stroke_smooth_stroke, 2191 VIEW3D_PT_tools_brush_falloff, 2192 VIEW3D_PT_tools_brush_falloff_frontface, 2193 VIEW3D_PT_tools_brush_falloff_normal, 2194 VIEW3D_PT_tools_brush_display, 2195 2196 VIEW3D_PT_sculpt_dyntopo, 2197 VIEW3D_PT_sculpt_voxel_remesh, 2198 VIEW3D_PT_sculpt_symmetry, 2199 VIEW3D_PT_sculpt_symmetry_for_topbar, 2200 VIEW3D_PT_sculpt_options, 2201 VIEW3D_PT_sculpt_options_gravity, 2202 2203 VIEW3D_PT_tools_weightpaint_symmetry, 2204 VIEW3D_PT_tools_weightpaint_symmetry_for_topbar, 2205 VIEW3D_PT_tools_weightpaint_options, 2206 2207 VIEW3D_PT_tools_vertexpaint_symmetry, 2208 VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar, 2209 VIEW3D_PT_tools_vertexpaint_options, 2210 2211 VIEW3D_PT_mask, 2212 VIEW3D_PT_stencil_projectpaint, 2213 VIEW3D_PT_tools_imagepaint_options_cavity, 2214 2215 VIEW3D_PT_tools_imagepaint_symmetry, 2216 VIEW3D_PT_tools_imagepaint_options, 2217 2218 VIEW3D_PT_tools_imagepaint_options_external, 2219 VIEW3D_MT_tools_projectpaint_stencil, 2220 2221 VIEW3D_PT_tools_particlemode, 2222 VIEW3D_PT_tools_particlemode_options, 2223 VIEW3D_PT_tools_particlemode_options_shapecut, 2224 VIEW3D_PT_tools_particlemode_options_display, 2225 2226 VIEW3D_PT_gpencil_brush_presets, 2227 VIEW3D_PT_tools_grease_pencil_brush_select, 2228 VIEW3D_PT_tools_grease_pencil_brush_settings, 2229 VIEW3D_PT_tools_grease_pencil_brush_advanced, 2230 VIEW3D_PT_tools_grease_pencil_brush_stroke, 2231 VIEW3D_PT_tools_grease_pencil_brush_post_processing, 2232 VIEW3D_PT_tools_grease_pencil_brush_random, 2233 VIEW3D_PT_tools_grease_pencil_brush_stabilizer, 2234 VIEW3D_PT_tools_grease_pencil_paint_appearance, 2235 VIEW3D_PT_tools_grease_pencil_sculpt_select, 2236 VIEW3D_PT_tools_grease_pencil_sculpt_settings, 2237 VIEW3D_PT_tools_grease_pencil_sculpt_options, 2238 VIEW3D_PT_tools_grease_pencil_sculpt_appearance, 2239 VIEW3D_PT_tools_grease_pencil_weight_paint_select, 2240 VIEW3D_PT_tools_grease_pencil_weight_paint_settings, 2241 VIEW3D_PT_tools_grease_pencil_weight_appearance, 2242 VIEW3D_PT_tools_grease_pencil_vertex_paint_select, 2243 VIEW3D_PT_tools_grease_pencil_vertex_paint_settings, 2244 VIEW3D_PT_tools_grease_pencil_vertex_appearance, 2245 VIEW3D_PT_tools_grease_pencil_interpolate, 2246 VIEW3D_PT_tools_grease_pencil_brush_mixcolor, 2247 VIEW3D_PT_tools_grease_pencil_brush_mix_palette, 2248 2249 VIEW3D_PT_tools_grease_pencil_brush_paint_falloff, 2250 VIEW3D_PT_tools_grease_pencil_brush_sculpt_falloff, 2251 VIEW3D_PT_tools_grease_pencil_brush_weight_falloff, 2252 VIEW3D_PT_tools_grease_pencil_brush_vertex_color, 2253 VIEW3D_PT_tools_grease_pencil_brush_vertex_palette, 2254 VIEW3D_PT_tools_grease_pencil_brush_vertex_falloff, 2255) 2256 2257if __name__ == "__main__": # only for live edit. 2258 from bpy.utils import register_class 2259 for cls in classes: 2260 register_class(cls) 2261