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