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