Cleanup: use 'tool_settings' name everywhere in UI scripts
[blender.git] / release / scripts / startup / bl_ui / space_image.py
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>
20 import bpy
21 import math
22 from bpy.types import Header, Menu, Panel
23 from .properties_paint_common import (
24     UnifiedPaintPanel,
25     brush_texture_settings,
26     brush_texpaint_common,
27     brush_mask_texture_settings,
28 )
29 from .properties_grease_pencil_common import (
30     GreasePencilDrawingToolsPanel,
31     GreasePencilStrokeEditPanel,
32     GreasePencilStrokeSculptPanel,
33     GreasePencilBrushPanel,
34     GreasePencilBrushCurvesPanel,
35     GreasePencilDataPanel,
36     GreasePencilPaletteColorPanel,
37 )
38 from bpy.app.translations import pgettext_iface as iface_
39
40
41 class ImagePaintPanel(UnifiedPaintPanel):
42     bl_space_type = 'IMAGE_EDITOR'
43     bl_region_type = 'TOOLS'
44
45
46 class BrushButtonsPanel(UnifiedPaintPanel):
47     bl_space_type = 'IMAGE_EDITOR'
48     bl_region_type = 'TOOLS'
49
50     @classmethod
51     def poll(cls, context):
52         sima = context.space_data
53         tool_settings = context.tool_settings.image_paint
54         return sima.show_paint and tool_settings.brush
55
56
57 class UVToolsPanel:
58     bl_space_type = 'IMAGE_EDITOR'
59     bl_region_type = 'TOOLS'
60     bl_category = "Tools"
61
62     @classmethod
63     def poll(cls, context):
64         sima = context.space_data
65         return sima.show_uvedit and not context.tool_settings.use_uv_sculpt
66
67
68 class IMAGE_MT_view(Menu):
69     bl_label = "View"
70
71     def draw(self, context):
72         layout = self.layout
73
74         sima = context.space_data
75         uv = sima.uv_editor
76         tool_settings = context.tool_settings
77         paint = tool_settings.image_paint
78
79         show_uvedit = sima.show_uvedit
80         show_render = sima.show_render
81
82         layout.operator("image.properties", icon='MENU_PANEL')
83         layout.operator("image.toolshelf", icon='MENU_PANEL')
84
85         layout.separator()
86
87         layout.prop(sima, "use_realtime_update")
88         if show_uvedit:
89             layout.prop(tool_settings, "show_uv_local_view")
90
91         layout.prop(uv, "show_other_objects")
92         layout.prop(uv, "show_metadata")
93         if paint.brush and (context.image_paint_object or sima.mode == 'PAINT'):
94             layout.prop(uv, "show_texpaint")
95             layout.prop(tool_settings, "show_uv_local_view", text="Show Same Material")
96
97         layout.separator()
98
99         layout.operator("image.view_zoom_in")
100         layout.operator("image.view_zoom_out")
101
102         layout.separator()
103
104         ratios = ((1, 8), (1, 4), (1, 2), (1, 1), (2, 1), (4, 1), (8, 1))
105
106         for a, b in ratios:
107             layout.operator(
108                 "image.view_zoom_ratio",
109                 text=iface_(f"Zoom {a:d}:{b:d}"),
110                 translate=False,
111             ).ratio = a / b
112
113         layout.separator()
114
115         if show_uvedit:
116             layout.operator("image.view_selected")
117
118         layout.operator("image.view_all")
119         layout.operator("image.view_all", text="View Fit").fit_view = True
120
121         layout.separator()
122
123         if show_render:
124             layout.operator("image.render_border")
125             layout.operator("image.clear_render_border")
126
127             layout.separator()
128
129             layout.operator("image.cycle_render_slot", text="Render Slot Cycle Next")
130             layout.operator("image.cycle_render_slot", text="Render Slot Cycle Previous").reverse = True
131             layout.separator()
132
133         layout.operator("screen.area_dupli")
134         layout.operator("screen.screen_full_area")
135         layout.operator("screen.screen_full_area", text="Toggle Fullscreen Area").use_hide_panels = True
136
137
138 class IMAGE_MT_select(Menu):
139     bl_label = "Select"
140
141     def draw(self, context):
142         layout = self.layout
143
144         layout.operator("uv.select_border").pinned = False
145         layout.operator("uv.select_border", text="Border Select Pinned").pinned = True
146         layout.operator("uv.circle_select")
147
148         layout.separator()
149
150         layout.operator("uv.select_all").action = 'TOGGLE'
151         layout.operator("uv.select_all", text="Inverse").action = 'INVERT'
152
153         layout.separator()
154
155         layout.operator("uv.select_pinned")
156         layout.operator("uv.select_linked").extend = False
157
158         layout.separator()
159
160         layout.operator("uv.select_less", text="Less")
161         layout.operator("uv.select_more", text="More")
162
163         layout.separator()
164
165         layout.operator("uv.select_split")
166
167
168 class IMAGE_MT_brush(Menu):
169     bl_label = "Brush"
170
171     def draw(self, context):
172         layout = self.layout
173         tool_settings = context.tool_settings
174         settings = tool_settings.image_paint
175         brush = settings.brush
176
177         ups = context.tool_settings.unified_paint_settings
178         layout.prop(ups, "use_unified_size", text="Unified Size")
179         layout.prop(ups, "use_unified_strength", text="Unified Strength")
180         layout.prop(ups, "use_unified_color", text="Unified Color")
181         layout.separator()
182
183         # brush tool
184         layout.prop_menu_enum(brush, "image_tool")
185
186
187 class IMAGE_MT_image(Menu):
188     bl_label = "Image"
189
190     def draw(self, context):
191         layout = self.layout
192
193         sima = context.space_data
194         ima = sima.image
195
196         layout.operator("image.new")
197         layout.operator("image.open")
198
199         show_render = sima.show_render
200
201         layout.operator("image.read_renderlayers")
202
203         layout.operator("image.save_dirty", text="Save All Images")
204
205         if ima:
206             if not show_render:
207                 layout.operator("image.replace")
208                 layout.operator("image.reload")
209
210             layout.operator("image.save")
211             layout.operator("image.save_as")
212             layout.operator("image.save_as", text="Save a Copy").copy = True
213
214             if ima.source == 'SEQUENCE':
215                 layout.operator("image.save_sequence")
216
217             layout.operator("image.external_edit", "Edit Externally")
218
219             layout.separator()
220
221             layout.menu("IMAGE_MT_image_invert")
222
223             if not show_render:
224                 if not ima.packed_file:
225                     layout.separator()
226                     layout.operator("image.pack")
227
228                 # only for dirty && specific image types, perhaps
229                 # this could be done in operator poll too
230                 if ima.is_dirty:
231                     if ima.source in {'FILE', 'GENERATED'} and ima.type != 'OPEN_EXR_MULTILAYER':
232                         if ima.packed_file:
233                             layout.separator()
234                         layout.operator("image.pack", text="Pack As PNG").as_png = True
235
236
237 class IMAGE_MT_image_invert(Menu):
238     bl_label = "Invert"
239
240     def draw(self, context):
241         layout = self.layout
242
243         props = layout.operator("image.invert", text="Invert Image Colors")
244         props.invert_r = True
245         props.invert_g = True
246         props.invert_b = True
247
248         layout.separator()
249
250         layout.operator("image.invert", text="Invert Red Channel").invert_r = True
251         layout.operator("image.invert", text="Invert Green Channel").invert_g = True
252         layout.operator("image.invert", text="Invert Blue Channel").invert_b = True
253         layout.operator("image.invert", text="Invert Alpha Channel").invert_a = True
254
255
256 class IMAGE_MT_uvs_showhide(Menu):
257     bl_label = "Show/Hide Faces"
258
259     def draw(self, context):
260         layout = self.layout
261
262         layout.operator("uv.reveal")
263         layout.operator("uv.hide", text="Hide Selected").unselected = False
264         layout.operator("uv.hide", text="Hide Unselected").unselected = True
265
266
267 class IMAGE_MT_uvs_proportional(Menu):
268     bl_label = "Proportional Editing"
269
270     def draw(self, context):
271         layout = self.layout
272
273         layout.props_enum(context.tool_settings, "proportional_edit")
274
275         layout.separator()
276
277         layout.label("Falloff:")
278         layout.props_enum(context.tool_settings, "proportional_edit_falloff")
279
280
281 class IMAGE_MT_uvs_transform(Menu):
282     bl_label = "Transform"
283
284     def draw(self, context):
285         layout = self.layout
286
287         layout.operator("transform.translate")
288         layout.operator("transform.rotate")
289         layout.operator("transform.resize")
290
291         layout.separator()
292
293         layout.operator("transform.shear")
294
295
296 class IMAGE_MT_uvs_snap(Menu):
297     bl_label = "Snap"
298
299     def draw(self, context):
300         layout = self.layout
301
302         layout.operator_context = 'EXEC_REGION_WIN'
303
304         layout.operator("uv.snap_selected", text="Selected to Pixels").target = 'PIXELS'
305         layout.operator("uv.snap_selected", text="Selected to Cursor").target = 'CURSOR'
306         layout.operator("uv.snap_selected", text="Selected to Cursor (Offset)").target = 'CURSOR_OFFSET'
307         layout.operator("uv.snap_selected", text="Selected to Adjacent Unselected").target = 'ADJACENT_UNSELECTED'
308
309         layout.separator()
310
311         layout.operator("uv.snap_cursor", text="Cursor to Pixels").target = 'PIXELS'
312         layout.operator("uv.snap_cursor", text="Cursor to Selected").target = 'SELECTED'
313
314
315 class IMAGE_MT_uvs_mirror(Menu):
316     bl_label = "Mirror"
317
318     def draw(self, context):
319         layout = self.layout
320
321         layout.operator_context = 'EXEC_REGION_WIN'
322
323         layout.operator("transform.mirror", text="X Axis").constraint_axis[0] = True
324         layout.operator("transform.mirror", text="Y Axis").constraint_axis[1] = True
325
326
327 class IMAGE_MT_uvs_weldalign(Menu):
328     bl_label = "Weld/Align"
329
330     def draw(self, context):
331         layout = self.layout
332
333         layout.operator("uv.weld")  # W, 1
334         layout.operator("uv.remove_doubles")
335         layout.operator_enum("uv.align", "axis")  # W, 2/3/4
336
337
338 class IMAGE_MT_uvs(Menu):
339     bl_label = "UVs"
340
341     def draw(self, context):
342         layout = self.layout
343
344         sima = context.space_data
345         uv = sima.uv_editor
346         tool_settings = context.tool_settings
347
348         layout.prop(uv, "use_snap_to_pixels")
349         layout.prop(uv, "lock_bounds")
350
351         layout.separator()
352
353         layout.prop(tool_settings, "use_uv_sculpt")
354
355         layout.separator()
356
357         layout.prop(uv, "use_live_unwrap")
358         layout.operator("uv.unwrap")
359         layout.operator("uv.pin", text="Unpin").clear = True
360         layout.operator("uv.pin").clear = False
361
362         layout.separator()
363
364         layout.operator("uv.pack_islands")
365         layout.operator("uv.average_islands_scale")
366         layout.operator("uv.minimize_stretch")
367         layout.operator("uv.stitch")
368         layout.operator("uv.mark_seam").clear = False
369         layout.operator("uv.mark_seam", text="Clear Seam").clear = True
370         layout.operator("uv.seams_from_islands")
371         layout.operator("mesh.faces_mirror_uv")
372
373         layout.separator()
374
375         layout.menu("IMAGE_MT_uvs_transform")
376         layout.menu("IMAGE_MT_uvs_mirror")
377         layout.menu("IMAGE_MT_uvs_snap")
378         layout.menu("IMAGE_MT_uvs_weldalign")
379
380         layout.separator()
381
382         layout.menu("IMAGE_MT_uvs_proportional")
383
384         layout.separator()
385
386         layout.menu("IMAGE_MT_uvs_showhide")
387
388
389 class IMAGE_MT_uvs_select_mode(Menu):
390     bl_label = "UV Select Mode"
391
392     def draw(self, context):
393         layout = self.layout
394
395         layout.operator_context = 'INVOKE_REGION_WIN'
396         tool_settings = context.tool_settings
397
398         # do smart things depending on whether uv_select_sync is on
399
400         if tool_settings.use_uv_select_sync:
401             props = layout.operator("wm.context_set_value", text="Vertex", icon='VERTEXSEL')
402             props.value = "(True, False, False)"
403             props.data_path = "tool_settings.mesh_select_mode"
404
405             props = layout.operator("wm.context_set_value", text="Edge", icon='EDGESEL')
406             props.value = "(False, True, False)"
407             props.data_path = "tool_settings.mesh_select_mode"
408
409             props = layout.operator("wm.context_set_value", text="Face", icon='FACESEL')
410             props.value = "(False, False, True)"
411             props.data_path = "tool_settings.mesh_select_mode"
412
413         else:
414             props = layout.operator("wm.context_set_string", text="Vertex", icon='UV_VERTEXSEL')
415             props.value = 'VERTEX'
416             props.data_path = "tool_settings.uv_select_mode"
417
418             props = layout.operator("wm.context_set_string", text="Edge", icon='UV_EDGESEL')
419             props.value = 'EDGE'
420             props.data_path = "tool_settings.uv_select_mode"
421
422             props = layout.operator("wm.context_set_string", text="Face", icon='UV_FACESEL')
423             props.value = 'FACE'
424             props.data_path = "tool_settings.uv_select_mode"
425
426             props = layout.operator("wm.context_set_string", text="Island", icon='UV_ISLANDSEL')
427             props.value = 'ISLAND'
428             props.data_path = "tool_settings.uv_select_mode"
429
430
431 class IMAGE_HT_header(Header):
432     bl_space_type = 'IMAGE_EDITOR'
433
434     def draw(self, context):
435         layout = self.layout
436
437         sima = context.space_data
438         ima = sima.image
439         iuser = sima.image_user
440         tool_settings = context.tool_settings
441         mode = sima.mode
442
443         show_render = sima.show_render
444         show_uvedit = sima.show_uvedit
445         show_maskedit = sima.show_maskedit
446
447         row = layout.row(align=True)
448         row.template_header()
449
450         MASK_MT_editor_menus.draw_collapsible(context, layout)
451
452         layout.template_ID(sima, "image", new="image.new", open="image.open")
453         if not show_render:
454             layout.prop(sima, "use_image_pin", text="")
455
456         layout.prop(sima, "mode", text="")
457
458         if show_maskedit:
459             row = layout.row()
460             row.template_ID(sima, "mask", new="mask.new")
461
462         layout.prop(sima, "pivot_point", icon_only=True)
463
464         # uv editing
465         if show_uvedit:
466             uvedit = sima.uv_editor
467
468             layout.prop(tool_settings, "use_uv_select_sync", text="")
469
470             if tool_settings.use_uv_select_sync:
471                 layout.template_edit_mode_selection()
472             else:
473                 layout.prop(tool_settings, "uv_select_mode", text="", expand=True)
474                 layout.prop(uvedit, "sticky_select_mode", icon_only=True)
475
476             row = layout.row(align=True)
477             row.prop(tool_settings, "proportional_edit", icon_only=True)
478             if tool_settings.proportional_edit != 'DISABLED':
479                 row.prop(tool_settings, "proportional_edit_falloff", icon_only=True)
480
481             row = layout.row(align=True)
482             row.prop(tool_settings, "use_snap", text="")
483             row.prop(tool_settings, "snap_uv_element", icon_only=True)
484             if tool_settings.snap_uv_element != 'INCREMENT':
485                 row.prop(tool_settings, "snap_target", text="")
486
487             mesh = context.edit_object.data
488             layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="")
489
490         if ima:
491             if ima.is_stereo_3d:
492                 row = layout.row()
493                 row.prop(sima, "show_stereo_3d", text="")
494
495             # layers
496             layout.template_image_layers(ima, iuser)
497
498             # draw options
499             row = layout.row(align=True)
500             row.prop(sima, "draw_channels", text="", expand=True)
501
502             row = layout.row(align=True)
503             if ima.type == 'COMPOSITE':
504                 row.operator("image.record_composite", icon='REC')
505             if ima.type == 'COMPOSITE' and ima.source in {'MOVIE', 'SEQUENCE'}:
506                 row.operator("image.play_composite", icon='PLAY')
507
508         if show_uvedit or show_maskedit or mode == 'PAINT':
509             layout.prop(sima, "use_realtime_update", icon_only=True, icon='LOCKED')
510
511
512 class MASK_MT_editor_menus(Menu):
513     bl_idname = "MASK_MT_editor_menus"
514     bl_label = ""
515
516     def draw(self, context):
517         self.draw_menus(self.layout, context)
518
519     @staticmethod
520     def draw_menus(layout, context):
521         sima = context.space_data
522         ima = sima.image
523
524         show_uvedit = sima.show_uvedit
525         show_maskedit = sima.show_maskedit
526         show_paint = sima.show_paint
527
528         layout.menu("IMAGE_MT_view")
529
530         if show_uvedit:
531             layout.menu("IMAGE_MT_select")
532         if show_maskedit:
533             layout.menu("MASK_MT_select")
534         if show_paint:
535             layout.menu("IMAGE_MT_brush")
536
537         if ima and ima.is_dirty:
538             layout.menu("IMAGE_MT_image", text="Image*")
539         else:
540             layout.menu("IMAGE_MT_image", text="Image")
541
542         if show_uvedit:
543             layout.menu("IMAGE_MT_uvs")
544         if show_maskedit:
545             layout.menu("MASK_MT_mask")
546
547
548 # -----------------------------------------------------------------------------
549 # Mask (similar code in space_clip.py, keep in sync)
550 # note! - panel placement does _not_ fit well with image panels... need to fix
551
552 from .properties_mask_common import (
553     MASK_PT_mask,
554     MASK_PT_layers,
555     MASK_PT_spline,
556     MASK_PT_point,
557     MASK_PT_display,
558     MASK_PT_tools,
559     MASK_PT_add,
560 )
561
562
563 class IMAGE_PT_mask(MASK_PT_mask, Panel):
564     bl_space_type = 'IMAGE_EDITOR'
565     bl_region_type = 'UI'
566
567
568 class IMAGE_PT_mask_layers(MASK_PT_layers, Panel):
569     bl_space_type = 'IMAGE_EDITOR'
570     bl_region_type = 'UI'
571
572
573 class IMAGE_PT_mask_display(MASK_PT_display, Panel):
574     bl_space_type = 'IMAGE_EDITOR'
575     bl_region_type = 'UI'
576
577
578 class IMAGE_PT_active_mask_spline(MASK_PT_spline, Panel):
579     bl_space_type = 'IMAGE_EDITOR'
580     bl_region_type = 'UI'
581
582
583 class IMAGE_PT_active_mask_point(MASK_PT_point, Panel):
584     bl_space_type = 'IMAGE_EDITOR'
585     bl_region_type = 'UI'
586
587
588 class IMAGE_PT_tools_mask(MASK_PT_tools, Panel):
589     bl_space_type = 'IMAGE_EDITOR'
590     bl_region_type = 'TOOLS'
591     bl_category = 'Mask'
592
593
594 class IMAGE_PT_tools_mask_add(MASK_PT_add, Panel):
595     bl_space_type = 'IMAGE_EDITOR'
596     bl_region_type = 'TOOLS'
597     bl_category = 'Mask'
598
599
600 # --- end mask ---
601
602
603 class IMAGE_PT_image_properties(Panel):
604     bl_space_type = 'IMAGE_EDITOR'
605     bl_region_type = 'UI'
606     bl_label = "Image"
607
608     @classmethod
609     def poll(cls, context):
610         sima = context.space_data
611         return (sima.image)
612
613     def draw(self, context):
614         layout = self.layout
615
616         sima = context.space_data
617         iuser = sima.image_user
618
619         layout.template_image(sima, "image", iuser, multiview=True)
620
621
622 class IMAGE_PT_game_properties(Panel):
623     bl_space_type = 'IMAGE_EDITOR'
624     bl_region_type = 'UI'
625     bl_label = "Game Properties"
626
627     @classmethod
628     def poll(cls, context):
629         sima = context.space_data
630         # display even when not in game mode because these settings effect the 3d view
631         return (sima and sima.image and not sima.show_maskedit)  # and (rd.engine == 'BLENDER_GAME')
632
633     def draw(self, context):
634         layout = self.layout
635
636         sima = context.space_data
637         ima = sima.image
638
639         split = layout.split()
640         col = split.column()
641         col.prop(ima, "use_animation")
642         sub = col.column(align=True)
643         sub.active = ima.use_animation
644         sub.prop(ima, "frame_start", text="Start")
645         sub.prop(ima, "frame_end", text="End")
646         sub.prop(ima, "fps", text="Speed")
647
648         col = split.column()
649         col.prop(ima, "use_tiles")
650         sub = col.column(align=True)
651         sub.active = ima.use_tiles or ima.use_animation
652         sub.prop(ima, "tiles_x", text="X")
653         sub.prop(ima, "tiles_y", text="Y")
654
655         split = layout.split()
656         col = split.column()
657         col.label(text="Clamp:")
658         col.prop(ima, "use_clamp_x", text="X")
659         col.prop(ima, "use_clamp_y", text="Y")
660
661         col = split.column()
662         col.label(text="Mapping:")
663         col.prop(ima, "mapping", expand=True)
664
665
666 class IMAGE_PT_view_properties(Panel):
667     bl_space_type = 'IMAGE_EDITOR'
668     bl_region_type = 'UI'
669     bl_label = "Display"
670
671     @classmethod
672     def poll(cls, context):
673         sima = context.space_data
674         return (sima and (sima.image or sima.show_uvedit))
675
676     def draw(self, context):
677         layout = self.layout
678
679         sima = context.space_data
680         ima = sima.image
681
682         show_render = sima.show_render
683         show_uvedit = sima.show_uvedit
684         show_maskedit = sima.show_maskedit
685         uvedit = sima.uv_editor
686
687         split = layout.split()
688
689         col = split.column()
690         if ima:
691             col.prop(ima, "display_aspect", text="Aspect Ratio")
692
693             col = split.column()
694             col.label(text="Coordinates:")
695             col.prop(sima, "show_repeat", text="Repeat")
696             if show_uvedit:
697                 col.prop(uvedit, "show_normalized_coords", text="Normalized")
698
699         elif show_uvedit:
700             col.label(text="Coordinates:")
701             col.prop(uvedit, "show_normalized_coords", text="Normalized")
702
703         if show_uvedit or show_maskedit:
704             col = layout.column()
705             col.label("Cursor Location:")
706             col.row().prop(sima, "cursor_location", text="")
707
708         if show_uvedit:
709             col.separator()
710
711             col.label(text="UVs:")
712             col.row().prop(uvedit, "edge_draw_type", expand=True)
713
714             split = layout.split()
715
716             col = split.column()
717             col.prop(uvedit, "show_faces")
718             col.prop(uvedit, "show_smooth_edges", text="Smooth")
719             col.prop(uvedit, "show_modified_edges", text="Modified")
720
721             col = split.column()
722             col.prop(uvedit, "show_stretch", text="Stretch")
723             sub = col.column()
724             sub.active = uvedit.show_stretch
725             sub.row().prop(uvedit, "draw_stretch_type", expand=True)
726
727             col = layout.column()
728             col.prop(uvedit, "show_other_objects")
729             row = col.row()
730             row.active = uvedit.show_other_objects
731             row.prop(uvedit, "other_uv_filter", text="Filter")
732
733         if show_render and ima:
734             layout.separator()
735             render_slot = ima.render_slots.active
736             layout.prop(render_slot, "name", text="Slot Name")
737
738
739 class IMAGE_PT_tools_transform_uvs(Panel, UVToolsPanel):
740     bl_label = "Transform"
741
742     @classmethod
743     def poll(cls, context):
744         sima = context.space_data
745         return sima.show_uvedit and not context.tool_settings.use_uv_sculpt
746
747     def draw(self, context):
748         layout = self.layout
749
750         col = layout.column(align=True)
751         col.operator("transform.translate")
752         col.operator("transform.rotate")
753         col.operator("transform.resize", text="Scale")
754         col.operator("transform.shear")
755
756
757 class IMAGE_PT_tools_align_uvs(Panel, UVToolsPanel):
758     bl_label = "UV Align"
759
760     @classmethod
761     def poll(cls, context):
762         sima = context.space_data
763         return sima.show_uvedit and not context.tool_settings.use_uv_sculpt
764
765     def draw(self, context):
766         layout = self.layout
767         layout.operator_context = 'EXEC_REGION_WIN'
768
769         split = layout.split()
770         col = split.column(align=True)
771         col.operator("transform.mirror", text="Mirror X").constraint_axis[0] = True
772         col.operator("transform.mirror", text="Mirror Y").constraint_axis[1] = True
773         col = split.column(align=True)
774         col.operator("transform.rotate", text="Rotate +90°").value = math.pi / 2
775         col.operator("transform.rotate", text="Rotate  - 90°").value = math.pi / -2
776
777         split = layout.split()
778         col = split.column(align=True)
779         col.operator("uv.align", text="Straighten").axis = 'ALIGN_S'
780         col.operator("uv.align", text="Straighten X").axis = 'ALIGN_T'
781         col.operator("uv.align", text="Straighten Y").axis = 'ALIGN_U'
782         col = split.column(align=True)
783         col.operator("uv.align", text="Align Auto").axis = 'ALIGN_AUTO'
784         col.operator("uv.align", text="Align X").axis = 'ALIGN_X'
785         col.operator("uv.align", text="Align Y").axis = 'ALIGN_Y'
786
787
788 class IMAGE_PT_tools_uvs(Panel, UVToolsPanel):
789     bl_label = "UV Tools"
790
791     @classmethod
792     def poll(cls, context):
793         sima = context.space_data
794         return sima.show_uvedit and not context.tool_settings.use_uv_sculpt
795
796     def draw(self, context):
797         layout = self.layout
798
799         col = layout.column(align=True)
800         row = col.row(align=True)
801         row.operator("uv.weld")
802         row.operator("uv.stitch")
803         col.operator("uv.remove_doubles")
804         col.operator("uv.average_islands_scale")
805         col.operator("uv.pack_islands")
806         col.operator("mesh.faces_mirror_uv")
807         col.operator("uv.minimize_stretch")
808
809         layout.label(text="UV Unwrap:")
810         row = layout.row(align=True)
811         row.operator("uv.pin").clear = False
812         row.operator("uv.pin", text="Unpin").clear = True
813         col = layout.column(align=True)
814         row = col.row(align=True)
815         row.operator("uv.mark_seam", text="Mark Seam").clear = False
816         row.operator("uv.mark_seam", text="Clear Seam").clear = True
817         col.operator("uv.seams_from_islands", text="Mark Seams from Islands")
818         col.operator("uv.unwrap")
819
820
821 class IMAGE_PT_paint(Panel, ImagePaintPanel):
822     bl_label = "Paint"
823     bl_category = "Tools"
824
825     def draw(self, context):
826         layout = self.layout
827
828         settings = context.tool_settings.image_paint
829         brush = settings.brush
830
831         col = layout.column()
832         col.template_ID_preview(settings, "brush", new="brush.add", rows=2, cols=6)
833
834         if brush:
835             brush_texpaint_common(self, context, layout, brush, settings)
836
837     @classmethod
838     def poll(cls, context):
839         sima = context.space_data
840         return sima.show_paint
841
842
843 class IMAGE_PT_tools_brush_overlay(BrushButtonsPanel, Panel):
844     bl_label = "Overlay"
845     bl_options = {'DEFAULT_CLOSED'}
846     bl_category = "Options"
847
848     def draw(self, context):
849         layout = self.layout
850
851         tool_settings = context.tool_settings.image_paint
852         brush = tool_settings.brush
853         tex_slot = brush.texture_slot
854         tex_slot_mask = brush.mask_texture_slot
855
856         col = layout.column()
857
858         col.label(text="Curve:")
859
860         row = col.row(align=True)
861         if brush.use_cursor_overlay:
862             row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
863         else:
864             row.prop(brush, "use_cursor_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
865
866         sub = row.row(align=True)
867         sub.prop(brush, "cursor_overlay_alpha", text="Alpha")
868         sub.prop(brush, "use_cursor_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
869
870         col.active = brush.brush_capabilities.has_overlay
871         col.label(text="Texture:")
872         row = col.row(align=True)
873         if tex_slot.map_mode != 'STENCIL':
874             if brush.use_primary_overlay:
875                 row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
876             else:
877                 row.prop(brush, "use_primary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
878
879         sub = row.row(align=True)
880         sub.prop(brush, "texture_overlay_alpha", text="Alpha")
881         sub.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
882
883         col.label(text="Mask Texture:")
884
885         row = col.row(align=True)
886         if tex_slot_mask.map_mode != 'STENCIL':
887             if brush.use_secondary_overlay:
888                 row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_OFF')
889             else:
890                 row.prop(brush, "use_secondary_overlay", toggle=True, text="", icon='RESTRICT_VIEW_ON')
891
892         sub = row.row(align=True)
893         sub.prop(brush, "mask_overlay_alpha", text="Alpha")
894         sub.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
895
896
897 class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, Panel):
898     bl_label = "Texture"
899     bl_options = {'DEFAULT_CLOSED'}
900     bl_category = "Tools"
901
902     def draw(self, context):
903         layout = self.layout
904
905         tool_settings = context.tool_settings.image_paint
906         brush = tool_settings.brush
907
908         col = layout.column()
909         col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
910
911         brush_texture_settings(col, brush, 0)
912
913
914 class IMAGE_PT_tools_mask_texture(BrushButtonsPanel, Panel):
915     bl_label = "Texture Mask"
916     bl_options = {'DEFAULT_CLOSED'}
917     bl_category = "Tools"
918
919     def draw(self, context):
920         layout = self.layout
921
922         brush = context.tool_settings.image_paint.brush
923
924         col = layout.column()
925
926         col.template_ID_preview(brush, "mask_texture", new="texture.new", rows=3, cols=8)
927
928         brush_mask_texture_settings(col, brush)
929
930
931 class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, Panel):
932     bl_label = "Tool"
933     bl_options = {'DEFAULT_CLOSED'}
934     bl_category = "Options"
935
936     def draw(self, context):
937         layout = self.layout
938         tool_settings = context.tool_settings.image_paint
939         brush = tool_settings.brush
940
941         layout.prop(brush, "image_tool", text="")
942
943         row = layout.row(align=True)
944         row.prop(brush, "use_paint_sculpt", text="", icon='SCULPTMODE_HLT')
945         row.prop(brush, "use_paint_vertex", text="", icon='VPAINT_HLT')
946         row.prop(brush, "use_paint_weight", text="", icon='WPAINT_HLT')
947         row.prop(brush, "use_paint_image", text="", icon='TPAINT_HLT')
948
949
950 class IMAGE_PT_paint_stroke(BrushButtonsPanel, Panel):
951     bl_label = "Paint Stroke"
952     bl_options = {'DEFAULT_CLOSED'}
953     bl_category = "Tools"
954
955     def draw(self, context):
956         layout = self.layout
957
958         tool_settings = context.tool_settings.image_paint
959         brush = tool_settings.brush
960
961         col = layout.column()
962
963         col.label(text="Stroke Method:")
964
965         col.prop(brush, "stroke_method", text="")
966
967         if brush.use_anchor:
968             col.separator()
969             col.prop(brush, "use_edge_to_edge", "Edge To Edge")
970
971         if brush.use_airbrush:
972             col.separator()
973             col.prop(brush, "rate", text="Rate", slider=True)
974
975         if brush.use_space:
976             col.separator()
977             row = col.row(align=True)
978             row.prop(brush, "spacing", text="Spacing")
979             row.prop(brush, "use_pressure_spacing", toggle=True, text="")
980
981         if brush.use_line or brush.use_curve:
982             col.separator()
983             row = col.row(align=True)
984             row.prop(brush, "spacing", text="Spacing")
985
986         if brush.use_curve:
987             col.separator()
988             col.template_ID(brush, "paint_curve", new="paintcurve.new")
989             col.operator("paintcurve.draw")
990
991         col = layout.column()
992         col.separator()
993
994         row = col.row(align=True)
995         row.prop(brush, "use_relative_jitter", icon_only=True)
996         if brush.use_relative_jitter:
997             row.prop(brush, "jitter", slider=True)
998         else:
999             row.prop(brush, "jitter_absolute")
1000         row.prop(brush, "use_pressure_jitter", toggle=True, text="")
1001
1002         col = layout.column()
1003         col.separator()
1004
1005         if brush.brush_capabilities.has_smooth_stroke:
1006             col.prop(brush, "use_smooth_stroke")
1007
1008             sub = col.column()
1009             sub.active = brush.use_smooth_stroke
1010             sub.prop(brush, "smooth_stroke_radius", text="Radius", slider=True)
1011             sub.prop(brush, "smooth_stroke_factor", text="Factor", slider=True)
1012
1013             col.separator()
1014
1015         col.prop(tool_settings, "input_samples")
1016
1017
1018 class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel):
1019     bl_label = "Paint Curve"
1020     bl_options = {'DEFAULT_CLOSED'}
1021     bl_category = "Tools"
1022
1023     def draw(self, context):
1024         layout = self.layout
1025
1026         tool_settings = context.tool_settings.image_paint
1027         brush = tool_settings.brush
1028
1029         layout.template_curve_mapping(brush, "curve")
1030
1031         col = layout.column(align=True)
1032         row = col.row(align=True)
1033         row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
1034         row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
1035         row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
1036         row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
1037         row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
1038         row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
1039
1040
1041 class IMAGE_PT_tools_imagepaint_symmetry(BrushButtonsPanel, Panel):
1042     bl_category = "Tools"
1043     bl_context = "imagepaint"
1044     bl_label = "Tiling"
1045     bl_options = {'DEFAULT_CLOSED'}
1046
1047     def draw(self, context):
1048         layout = self.layout
1049
1050         tool_settings = context.tool_settings
1051         ipaint = tool_settings.image_paint
1052
1053         col = layout.column(align=True)
1054         row = col.row(align=True)
1055         row.prop(ipaint, "tile_x", text="X", toggle=True)
1056         row.prop(ipaint, "tile_y", text="Y", toggle=True)
1057
1058
1059 class IMAGE_PT_tools_brush_appearance(BrushButtonsPanel, Panel):
1060     bl_label = "Appearance"
1061     bl_options = {'DEFAULT_CLOSED'}
1062     bl_category = "Options"
1063
1064     def draw(self, context):
1065         layout = self.layout
1066
1067         tool_settings = context.tool_settings.image_paint
1068         brush = tool_settings.brush
1069
1070         if brush is None:  # unlikely but can happen
1071             layout.label(text="Brush Unset")
1072             return
1073
1074         col = layout.column(align=True)
1075
1076         col.prop(tool_settings, "show_brush")
1077         sub = col.column()
1078         sub.active = tool_settings.show_brush
1079         sub.prop(brush, "cursor_color_add", text="")
1080
1081         col.separator()
1082
1083         col.prop(brush, "use_custom_icon")
1084         sub = col.column()
1085         sub.active = brush.use_custom_icon
1086         sub.prop(brush, "icon_filepath", text="")
1087
1088
1089 class IMAGE_PT_tools_paint_options(BrushButtonsPanel, Panel):
1090     bl_label = "Image Paint"
1091     bl_category = "Options"
1092
1093     def draw(self, context):
1094         layout = self.layout
1095
1096         tool_settings = context.tool_settings
1097         # brush = tool_settings.image_paint.brush
1098
1099         ups = tool_settings.unified_paint_settings
1100
1101         col = layout.column(align=True)
1102         col.label(text="Unified Settings:")
1103         row = col.row()
1104         row.prop(ups, "use_unified_size", text="Size")
1105         row.prop(ups, "use_unified_strength", text="Strength")
1106         col.prop(ups, "use_unified_color", text="Color")
1107
1108
1109 class IMAGE_PT_uv_sculpt_curve(Panel):
1110     bl_space_type = 'IMAGE_EDITOR'
1111     bl_region_type = 'TOOLS'
1112     bl_label = "UV Sculpt Curve"
1113     bl_category = "Tools"
1114     bl_options = {'DEFAULT_CLOSED'}
1115
1116     @classmethod
1117     def poll(cls, context):
1118         sima = context.space_data
1119         tool_settings = context.tool_settings.image_paint
1120         return sima.show_uvedit and context.tool_settings.use_uv_sculpt and not (sima.show_paint and tool_settings.brush)
1121
1122     def draw(self, context):
1123         layout = self.layout
1124
1125         tool_settings = context.tool_settings
1126         uvsculpt = tool_settings.uv_sculpt
1127         brush = uvsculpt.brush
1128
1129         layout.template_curve_mapping(brush, "curve")
1130
1131         row = layout.row(align=True)
1132         row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH'
1133         row.operator("brush.curve_preset", icon='SPHERECURVE', text="").shape = 'ROUND'
1134         row.operator("brush.curve_preset", icon='ROOTCURVE', text="").shape = 'ROOT'
1135         row.operator("brush.curve_preset", icon='SHARPCURVE', text="").shape = 'SHARP'
1136         row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE'
1137         row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX'
1138
1139
1140 class IMAGE_PT_uv_sculpt(Panel, ImagePaintPanel):
1141     bl_space_type = 'IMAGE_EDITOR'
1142     bl_region_type = 'TOOLS'
1143     bl_category = "Tools"
1144     bl_label = "UV Sculpt"
1145
1146     @classmethod
1147     def poll(cls, context):
1148         sima = context.space_data
1149         tool_settings = context.tool_settings.image_paint
1150         return sima.show_uvedit and context.tool_settings.use_uv_sculpt and not (sima.show_paint and tool_settings.brush)
1151
1152     def draw(self, context):
1153         layout = self.layout
1154
1155         tool_settings = context.tool_settings
1156         uvsculpt = tool_settings.uv_sculpt
1157         brush = uvsculpt.brush
1158
1159         if brush:
1160             col = layout.column()
1161
1162             row = col.row(align=True)
1163             self.prop_unified_size(row, context, brush, "size", slider=True, text="Radius")
1164             self.prop_unified_size(row, context, brush, "use_pressure_size")
1165
1166             row = col.row(align=True)
1167             self.prop_unified_strength(row, context, brush, "strength", slider=True, text="Strength")
1168             self.prop_unified_strength(row, context, brush, "use_pressure_strength")
1169
1170         col = layout.column()
1171         col.prop(tool_settings, "uv_sculpt_lock_borders")
1172         col.prop(tool_settings, "uv_sculpt_all_islands")
1173
1174         col.prop(tool_settings, "uv_sculpt_tool")
1175         if tool_settings.uv_sculpt_tool == 'RELAX':
1176             col.prop(tool_settings, "uv_relax_method")
1177
1178         col.prop(uvsculpt, "show_brush")
1179
1180
1181 class IMAGE_PT_options_uvs(Panel, UVToolsPanel):
1182     bl_label = "UV Options"
1183     bl_category = "Options"
1184
1185     @classmethod
1186     def poll(cls, context):
1187         sima = context.space_data
1188         return sima.show_uvedit
1189
1190     def draw(self, context):
1191         layout = self.layout
1192
1193         sima = context.space_data
1194         uv = sima.uv_editor
1195         tool_settings = context.tool_settings
1196
1197         col = layout.column(align=True)
1198         col.prop(tool_settings, "use_uv_sculpt")
1199         col.prop(uv, "use_live_unwrap")
1200         col.prop(uv, "use_snap_to_pixels")
1201         col.prop(uv, "lock_bounds")
1202
1203
1204 class ImageScopesPanel:
1205     @classmethod
1206     def poll(cls, context):
1207         sima = context.space_data
1208         if not (sima and sima.image):
1209             return False
1210         # scopes are not updated in paint modes, hide
1211         if sima.mode == 'PAINT':
1212             return False
1213         ob = context.active_object
1214         if ob and ob.mode in {'TEXTURE_PAINT', 'EDIT'}:
1215             return False
1216         return True
1217
1218
1219 class IMAGE_PT_view_histogram(ImageScopesPanel, Panel):
1220     bl_space_type = 'IMAGE_EDITOR'
1221     bl_region_type = 'TOOLS'
1222     bl_label = "Histogram"
1223     bl_category = "Scopes"
1224
1225     def draw(self, context):
1226         layout = self.layout
1227
1228         sima = context.space_data
1229         hist = sima.scopes.histogram
1230
1231         layout.template_histogram(sima.scopes, "histogram")
1232         row = layout.row(align=True)
1233         row.prop(hist, "mode", expand=True)
1234         row.prop(hist, "show_line", text="")
1235
1236
1237 class IMAGE_PT_view_waveform(ImageScopesPanel, Panel):
1238     bl_space_type = 'IMAGE_EDITOR'
1239     bl_region_type = 'TOOLS'
1240     bl_label = "Waveform"
1241     bl_category = "Scopes"
1242
1243     def draw(self, context):
1244         layout = self.layout
1245
1246         sima = context.space_data
1247
1248         layout.template_waveform(sima, "scopes")
1249         row = layout.split(percentage=0.75)
1250         row.prop(sima.scopes, "waveform_alpha")
1251         row.prop(sima.scopes, "waveform_mode", text="")
1252
1253
1254 class IMAGE_PT_view_vectorscope(ImageScopesPanel, Panel):
1255     bl_space_type = 'IMAGE_EDITOR'
1256     bl_region_type = 'TOOLS'
1257     bl_label = "Vectorscope"
1258     bl_category = "Scopes"
1259
1260     def draw(self, context):
1261         layout = self.layout
1262
1263         sima = context.space_data
1264         layout.template_vectorscope(sima, "scopes")
1265         layout.prop(sima.scopes, "vectorscope_alpha")
1266
1267
1268 class IMAGE_PT_sample_line(ImageScopesPanel, Panel):
1269     bl_space_type = 'IMAGE_EDITOR'
1270     bl_region_type = 'TOOLS'
1271     bl_label = "Sample Line"
1272     bl_category = "Scopes"
1273
1274     def draw(self, context):
1275         layout = self.layout
1276
1277         sima = context.space_data
1278         hist = sima.sample_histogram
1279
1280         layout.operator("image.sample_line")
1281         layout.template_histogram(sima, "sample_histogram")
1282         row = layout.row(align=True)
1283         row.prop(hist, "mode", expand=True)
1284         row.prop(hist, "show_line", text="")
1285
1286
1287 class IMAGE_PT_scope_sample(ImageScopesPanel, Panel):
1288     bl_space_type = 'IMAGE_EDITOR'
1289     bl_region_type = 'TOOLS'
1290     bl_label = "Scope Samples"
1291     bl_category = "Scopes"
1292
1293     def draw(self, context):
1294         layout = self.layout
1295
1296         sima = context.space_data
1297
1298         row = layout.row()
1299         row.prop(sima.scopes, "use_full_resolution")
1300         sub = row.row()
1301         sub.active = not sima.scopes.use_full_resolution
1302         sub.prop(sima.scopes, "accuracy")
1303
1304
1305 # Grease Pencil properties
1306 class IMAGE_PT_grease_pencil(GreasePencilDataPanel, Panel):
1307     bl_space_type = 'IMAGE_EDITOR'
1308     bl_region_type = 'UI'
1309
1310     # NOTE: this is just a wrapper around the generic GP Panel
1311
1312
1313 # Grease Pencil palette colors
1314 class IMAGE_PT_grease_pencil_palettecolor(GreasePencilPaletteColorPanel, Panel):
1315     bl_space_type = 'IMAGE_EDITOR'
1316     bl_region_type = 'UI'
1317
1318     # NOTE: this is just a wrapper around the generic GP Panel
1319
1320
1321 # Grease Pencil drawing tools
1322 class IMAGE_PT_tools_grease_pencil_draw(GreasePencilDrawingToolsPanel, Panel):
1323     bl_space_type = 'IMAGE_EDITOR'
1324
1325
1326 # Grease Pencil stroke editing tools
1327 class IMAGE_PT_tools_grease_pencil_edit(GreasePencilStrokeEditPanel, Panel):
1328     bl_space_type = 'IMAGE_EDITOR'
1329
1330
1331 # Grease Pencil stroke sculpting tools
1332 class IMAGE_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel):
1333     bl_space_type = 'IMAGE_EDITOR'
1334
1335
1336 # Grease Pencil drawing brushes
1337 class IMAGE_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel):
1338     bl_space_type = 'IMAGE_EDITOR'
1339
1340
1341 # Grease Pencil drawing curves
1342 class IMAGE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel):
1343     bl_space_type = 'IMAGE_EDITOR'
1344
1345
1346 classes = (
1347     IMAGE_MT_view,
1348     IMAGE_MT_select,
1349     IMAGE_MT_brush,
1350     IMAGE_MT_image,
1351     IMAGE_MT_image_invert,
1352     IMAGE_MT_uvs,
1353     IMAGE_MT_uvs_showhide,
1354     IMAGE_MT_uvs_proportional,
1355     IMAGE_MT_uvs_transform,
1356     IMAGE_MT_uvs_snap,
1357     IMAGE_MT_uvs_mirror,
1358     IMAGE_MT_uvs_weldalign,
1359     IMAGE_MT_uvs_select_mode,
1360     IMAGE_HT_header,
1361     MASK_MT_editor_menus,
1362     IMAGE_PT_mask,
1363     IMAGE_PT_tools_mask_add,
1364     IMAGE_PT_mask_layers,
1365     IMAGE_PT_mask_display,
1366     IMAGE_PT_active_mask_spline,
1367     IMAGE_PT_active_mask_point,
1368     IMAGE_PT_image_properties,
1369     IMAGE_PT_game_properties,
1370     IMAGE_PT_view_properties,
1371     IMAGE_PT_tools_transform_uvs,
1372     IMAGE_PT_tools_align_uvs,
1373     IMAGE_PT_tools_uvs,
1374     IMAGE_PT_options_uvs,
1375     IMAGE_PT_paint,
1376     IMAGE_PT_tools_brush_overlay,
1377     IMAGE_PT_tools_brush_texture,
1378     IMAGE_PT_tools_mask,
1379     IMAGE_PT_tools_mask_texture,
1380     IMAGE_PT_tools_brush_tool,
1381     IMAGE_PT_paint_stroke,
1382     IMAGE_PT_paint_curve,
1383     IMAGE_PT_tools_imagepaint_symmetry,
1384     IMAGE_PT_tools_brush_appearance,
1385     IMAGE_PT_tools_paint_options,
1386     IMAGE_PT_uv_sculpt,
1387     IMAGE_PT_uv_sculpt_curve,
1388     IMAGE_PT_view_histogram,
1389     IMAGE_PT_view_waveform,
1390     IMAGE_PT_view_vectorscope,
1391     IMAGE_PT_sample_line,
1392     IMAGE_PT_scope_sample,
1393     IMAGE_PT_grease_pencil,
1394     IMAGE_PT_grease_pencil_palettecolor,
1395     IMAGE_PT_tools_grease_pencil_draw,
1396     IMAGE_PT_tools_grease_pencil_edit,
1397     IMAGE_PT_tools_grease_pencil_sculpt,
1398     IMAGE_PT_tools_grease_pencil_brush,
1399     IMAGE_PT_tools_grease_pencil_brushcurves,
1400 )
1401
1402 if __name__ == "__main__":  # only for live edit.
1403     from bpy.utils import register_class
1404     for cls in classes:
1405         register_class(cls)