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