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