- clear some warnings
[blender.git] / release / scripts / 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
22
23 class BrushButtonsPanel():
24     bl_space_type = 'IMAGE_EDITOR'
25     bl_region_type = 'UI'
26
27     @classmethod
28     def poll(cls, context):
29         sima = context.space_data
30         toolsettings = context.tool_settings.image_paint
31         return sima.show_paint and toolsettings.brush
32
33
34 class IMAGE_MT_view(bpy.types.Menu):
35     bl_label = "View"
36
37     def draw(self, context):
38         layout = self.layout
39
40         sima = context.space_data
41         uv = sima.uv_editor
42         toolsettings = context.tool_settings
43
44         show_uvedit = sima.show_uvedit
45
46         layout.operator("image.properties", icon='MENU_PANEL')
47         layout.operator("image.scopes", icon='MENU_PANEL')
48
49         layout.separator()
50
51         layout.prop(sima, "use_realtime_update")
52         if show_uvedit:
53             layout.prop(toolsettings, "show_uv_local_view")
54             layout.prop(uv, "show_other_objects")
55
56         layout.separator()
57
58         layout.operator("image.view_zoom_in")
59         layout.operator("image.view_zoom_out")
60
61         layout.separator()
62
63         ratios = [[1, 8], [1, 4], [1, 2], [1, 1], [2, 1], [4, 1], [8, 1]]
64
65         for a, b in ratios:
66             text = "Zoom %d:%d" % (a, b)
67             layout.operator("image.view_zoom_ratio", text=text).ratio = a / b
68
69         layout.separator()
70
71         if show_uvedit:
72             layout.operator("image.view_selected")
73
74         layout.operator("image.view_all")
75
76         layout.separator()
77
78         layout.operator("screen.area_dupli")
79         layout.operator("screen.screen_full_area")
80
81
82 class IMAGE_MT_select(bpy.types.Menu):
83     bl_label = "Select"
84
85     def draw(self, context):
86         layout = self.layout
87
88         layout.operator("uv.select_border")
89         layout.operator("uv.select_border").pinned = True
90
91         layout.separator()
92
93         layout.operator("uv.select_all")
94         layout.operator("uv.select_inverse")
95         layout.operator("uv.unlink_selection")
96
97         layout.separator()
98
99         layout.operator("uv.select_pinned")
100         layout.operator("uv.select_linked")
101
102
103 class IMAGE_MT_image(bpy.types.Menu):
104     bl_label = "Image"
105
106     def draw(self, context):
107         layout = self.layout
108
109         sima = context.space_data
110         ima = sima.image
111
112         layout.operator("image.new")
113         layout.operator("image.open")
114
115         show_render = sima.show_render
116
117         if ima:
118             if not show_render:
119                 layout.operator("image.replace")
120                 layout.operator("image.reload")
121
122             layout.operator("image.save")
123             layout.operator("image.save_as")
124             layout.operator("image.save_as", text="Save a Copy").copy = True
125
126             if ima.source == 'SEQUENCE':
127                 layout.operator("image.save_sequence")
128
129             layout.operator("image.external_edit", "Edit Externally")
130
131             if not show_render:
132                 layout.separator()
133
134                 if ima.packed_file:
135                     layout.operator("image.unpack")
136                 else:
137                     layout.operator("image.pack")
138
139                 # only for dirty && specific image types, perhaps
140                 # this could be done in operator poll too
141                 if ima.is_dirty:
142                     if ima.source in ('FILE', 'GENERATED') and ima.type != 'MULTILAYER':
143                         layout.operator("image.pack", text="Pack As PNG").as_png = True
144
145             layout.separator()
146
147             layout.prop(sima, "use_image_paint")
148
149
150 class IMAGE_MT_uvs_showhide(bpy.types.Menu):
151     bl_label = "Show/Hide Faces"
152
153     def draw(self, context):
154         layout = self.layout
155
156         layout.operator("uv.reveal")
157         layout.operator("uv.hide", text="Hide Selected")
158         layout.operator("uv.hide", text="Hide Unselected").unselected = True
159
160
161 class IMAGE_MT_uvs_transform(bpy.types.Menu):
162     bl_label = "Transform"
163
164     def draw(self, context):
165         layout = self.layout
166
167         layout.operator("transform.translate")
168         layout.operator("transform.rotate")
169         layout.operator("transform.resize")
170
171
172 class IMAGE_MT_uvs_snap(bpy.types.Menu):
173     bl_label = "Snap"
174
175     def draw(self, context):
176         layout = self.layout
177         layout.operator_context = 'EXEC_REGION_WIN'
178
179         layout.operator("uv.snap_selection", text="Selected to Pixels").target = 'PIXELS'
180         layout.operator("uv.snap_selection", text="Selected to Cursor").target = 'CURSOR'
181         layout.operator("uv.snap_selection", text="Selected to Adjacent Unselected").target = 'ADJACENT_UNSELECTED'
182
183         layout.separator()
184
185         layout.operator("uv.snap_cursor", text="Cursor to Pixels").target = 'PIXELS'
186         layout.operator("uv.snap_cursor", text="Cursor to Selection").target = 'SELECTION'
187
188
189 class IMAGE_MT_uvs_mirror(bpy.types.Menu):
190     bl_label = "Mirror"
191
192     def draw(self, context):
193         layout = self.layout
194         layout.operator_context = 'EXEC_REGION_WIN'
195
196         layout.operator("transform.mirror", text="X Axis").constraint_axis[0] = True
197         layout.operator("transform.mirror", text="Y Axis").constraint_axis[1] = True
198
199
200 class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
201     bl_label = "Weld/Align"
202
203     def draw(self, context):
204         layout = self.layout
205
206         layout.operator("uv.weld")  # W, 1
207         layout.operator_enum("uv.align", "axis")  # W, 2/3/4
208
209
210 class IMAGE_MT_uvs(bpy.types.Menu):
211     bl_label = "UVs"
212
213     def draw(self, context):
214         layout = self.layout
215
216         sima = context.space_data
217         uv = sima.uv_editor
218         toolsettings = context.tool_settings
219
220         layout.prop(uv, "use_snap_to_pixels")
221         layout.prop(uv, "lock_bounds")
222
223         layout.separator()
224
225         layout.prop(uv, "use_live_unwrap")
226         layout.operator("uv.unwrap")
227         layout.operator("uv.pin", text="Unpin").clear = True
228         layout.operator("uv.pin")
229
230         layout.separator()
231
232         layout.operator("uv.pack_islands")
233         layout.operator("uv.average_islands_scale")
234         layout.operator("uv.minimize_stretch")
235         layout.operator("uv.stitch")
236         layout.operator("mesh.faces_miror_uv")
237
238         layout.separator()
239
240         layout.menu("IMAGE_MT_uvs_transform")
241         layout.menu("IMAGE_MT_uvs_mirror")
242         layout.menu("IMAGE_MT_uvs_snap")
243         layout.menu("IMAGE_MT_uvs_weldalign")
244
245         layout.separator()
246
247         layout.prop_menu_enum(toolsettings, "proportional_edit")
248         layout.prop_menu_enum(toolsettings, "proportional_edit_falloff")
249
250         layout.separator()
251
252         layout.menu("IMAGE_MT_uvs_showhide")
253
254
255 class IMAGE_MT_uvs_select_mode(bpy.types.Menu):
256     bl_label = "UV Select Mode"
257
258     def draw(self, context):
259         layout = self.layout
260
261         layout.operator_context = 'INVOKE_REGION_WIN'
262         toolsettings = context.tool_settings
263
264         # do smart things depending on whether uv_select_sync is on
265
266         if toolsettings.use_uv_select_sync:
267             prop = layout.operator("wm.context_set_value", text="Vertex", icon='VERTEXSEL')
268             prop.value = "(True, False, False)"
269             prop.data_path = "tool_settings.mesh_select_mode"
270
271             prop = layout.operator("wm.context_set_value", text="Edge", icon='EDGESEL')
272             prop.value = "(False, True, False)"
273             prop.data_path = "tool_settings.mesh_select_mode"
274
275             prop = layout.operator("wm.context_set_value", text="Face", icon='FACESEL')
276             prop.value = "(False, False, True)"
277             prop.data_path = "tool_settings.mesh_select_mode"
278
279         else:
280             prop = layout.operator("wm.context_set_string", text="Vertex", icon='UV_VERTEXSEL')
281             prop.value = "VERTEX"
282             prop.data_path = "tool_settings.uv_select_mode"
283
284             prop = layout.operator("wm.context_set_string", text="Edge", icon='UV_EDGESEL')
285             prop.value = "EDGE"
286             prop.data_path = "tool_settings.uv_select_mode"
287
288             prop = layout.operator("wm.context_set_string", text="Face", icon='UV_FACESEL')
289             prop.value = "FACE"
290             prop.data_path = "tool_settings.uv_select_mode"
291
292             prop = layout.operator("wm.context_set_string", text="Island", icon='UV_ISLANDSEL')
293             prop.value = "ISLAND"
294             prop.data_path = "tool_settings.uv_select_mode"
295
296
297 class IMAGE_HT_header(bpy.types.Header):
298     bl_space_type = 'IMAGE_EDITOR'
299
300     def draw(self, context):
301         layout = self.layout
302
303         sima = context.space_data
304         ima = sima.image
305         iuser = sima.image_user
306         toolsettings = context.tool_settings
307
308         show_render = sima.show_render
309         # show_paint = sima.show_paint
310         show_uvedit = sima.show_uvedit
311
312         row = layout.row(align=True)
313         row.template_header()
314
315         # menus
316         if context.area.show_menus:
317             sub = row.row(align=True)
318             sub.menu("IMAGE_MT_view")
319
320             if show_uvedit:
321                 sub.menu("IMAGE_MT_select")
322
323             if ima and ima.is_dirty:
324                 sub.menu("IMAGE_MT_image", text="Image*")
325             else:
326                 sub.menu("IMAGE_MT_image", text="Image")
327
328             if show_uvedit:
329                 sub.menu("IMAGE_MT_uvs")
330
331         layout.template_ID(sima, "image", new="image.new")
332         if not show_render:
333             layout.prop(sima, "use_image_pin", text="")
334
335         # uv editing
336         if show_uvedit:
337             uvedit = sima.uv_editor
338
339             layout.prop(uvedit, "pivot_point", text="", icon_only=True)
340             layout.prop(toolsettings, "use_uv_select_sync", text="")
341
342             if toolsettings.use_uv_select_sync:
343                 row = layout.row(align=True)
344                 row.prop(toolsettings, "mesh_select_mode", text="", index=0, icon='VERTEXSEL')
345                 row.prop(toolsettings, "mesh_select_mode", text="", index=1, icon='EDGESEL')
346                 row.prop(toolsettings, "mesh_select_mode", text="", index=2, icon='FACESEL')
347             else:
348                 layout.prop(toolsettings, "uv_select_mode", text="", expand=True)
349                 layout.prop(uvedit, "sticky_select_mode", text="", icon_only=True)
350
351             row = layout.row(align=True)
352             row.prop(toolsettings, "proportional_edit", text="", icon_only=True)
353             if toolsettings.proportional_edit != 'DISABLED':
354                 row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True)
355
356             row = layout.row(align=True)
357             row.prop(toolsettings, "use_snap", text="")
358             row.prop(toolsettings, "snap_element", text="", icon_only=True)
359
360             # mesh = context.edit_object.data
361             # row.prop_search(mesh.uv_textures, "active", mesh, "uv_textures")
362
363         if ima:
364             # layers
365             layout.template_image_layers(ima, iuser)
366
367             # painting
368             layout.prop(sima, "use_image_paint", text="")
369
370             # draw options
371             row = layout.row(align=True)
372             row.prop(sima, "draw_channels", text="", expand=True)
373
374             row = layout.row(align=True)
375             if ima.type == 'COMPOSITE':
376                 row.operator("image.record_composite", icon='REC')
377             if ima.type == 'COMPOSITE' and ima.source in ('MOVIE', 'SEQUENCE'):
378                 row.operator("image.play_composite", icon='PLAY')
379
380         if show_uvedit or sima.use_image_paint:
381             layout.prop(sima, "use_realtime_update", text="", icon_only=True, icon='LOCKED')
382
383
384 class IMAGE_PT_image_properties(bpy.types.Panel):
385     bl_space_type = 'IMAGE_EDITOR'
386     bl_region_type = 'UI'
387     bl_label = "Image"
388
389     @classmethod
390     def poll(cls, context):
391         sima = context.space_data
392         return (sima.image)
393
394     def draw(self, context):
395         layout = self.layout
396
397         sima = context.space_data
398         # ima = sima.image
399         iuser = sima.image_user
400
401         layout.template_image(sima, "image", iuser)
402
403
404 class IMAGE_PT_game_properties(bpy.types.Panel):
405     bl_space_type = 'IMAGE_EDITOR'
406     bl_region_type = 'UI'
407     bl_label = "Game Properties"
408
409     @classmethod
410     def poll(cls, context):
411         rd = context.scene.render
412         sima = context.space_data
413         return (sima and sima.image) and (rd.engine == 'BLENDER_GAME')
414
415     def draw(self, context):
416         layout = self.layout
417
418         sima = context.space_data
419         ima = sima.image
420
421         split = layout.split()
422
423         col = split.column()
424
425         sub = col.column(align=True)
426         sub.prop(ima, "use_animation")
427
428         subsub = sub.column()
429         subsub.active = ima.use_animation
430         subsub.prop(ima, "frame_start", text="Start")
431         subsub.prop(ima, "frame_end", text="End")
432         subsub.prop(ima, "fps", text="Speed")
433
434         col.prop(ima, "use_tiles")
435         sub = col.column(align=True)
436         sub.active = ima.use_tiles or ima.use_animation
437         sub.prop(ima, "tiles_x", text="X")
438         sub.prop(ima, "tiles_y", text="Y")
439
440         col = split.column()
441         col.label(text="Clamp:")
442         col.prop(ima, "use_clamp_x", text="X")
443         col.prop(ima, "use_clamp_y", text="Y")
444         col.separator()
445         col.prop(ima, "mapping", expand=True)
446
447
448 class IMAGE_PT_view_histogram(bpy.types.Panel):
449     bl_space_type = 'IMAGE_EDITOR'
450     bl_region_type = 'PREVIEW'
451     bl_label = "Histogram"
452
453     @classmethod
454     def poll(cls, context):
455         sima = context.space_data
456         return (sima and sima.image)
457
458     def draw(self, context):
459         layout = self.layout
460
461         sima = context.space_data
462
463         layout.template_histogram(sima.scopes, "histogram")
464         layout.prop(sima.scopes.histogram, "mode", icon_only=True)
465
466
467 class IMAGE_PT_view_waveform(bpy.types.Panel):
468     bl_space_type = 'IMAGE_EDITOR'
469     bl_region_type = 'PREVIEW'
470     bl_label = "Waveform"
471
472     @classmethod
473     def poll(cls, context):
474         sima = context.space_data
475         return (sima and sima.image)
476
477     def draw(self, context):
478         layout = self.layout
479
480         sima = context.space_data
481         layout.template_waveform(sima, "scopes")
482         sub = layout.row().split(percentage=0.75)
483         sub.prop(sima.scopes, "waveform_alpha")
484         sub.prop(sima.scopes, "waveform_mode", text="", icon_only=True)
485
486
487 class IMAGE_PT_view_vectorscope(bpy.types.Panel):
488     bl_space_type = 'IMAGE_EDITOR'
489     bl_region_type = 'PREVIEW'
490     bl_label = "Vectorscope"
491
492     @classmethod
493     def poll(cls, context):
494         sima = context.space_data
495         return (sima and sima.image)
496
497     def draw(self, context):
498         layout = self.layout
499
500         sima = context.space_data
501         layout.template_vectorscope(sima, "scopes")
502         layout.prop(sima.scopes, "vectorscope_alpha")
503
504
505 class IMAGE_PT_sample_line(bpy.types.Panel):
506     bl_space_type = 'IMAGE_EDITOR'
507     bl_region_type = 'PREVIEW'
508     bl_label = "Sample Line"
509
510     @classmethod
511     def poll(cls, context):
512         sima = context.space_data
513         return (sima and sima.image)
514
515     def draw(self, context):
516         layout = self.layout
517         layout.operator("image.sample_line")
518         sima = context.space_data
519         layout.template_histogram(sima, "sample_histogram")
520         layout.prop(sima.sample_histogram, "mode")
521
522
523 class IMAGE_PT_scope_sample(bpy.types.Panel):
524     bl_space_type = 'IMAGE_EDITOR'
525     bl_region_type = 'PREVIEW'
526     bl_label = "Scope Samples"
527
528     @classmethod
529     def poll(cls, context):
530         sima = context.space_data
531         return sima
532
533     def draw(self, context):
534         layout = self.layout
535         sima = context.space_data
536         split = layout.split()
537         row = split.row()
538         row.prop(sima.scopes, "use_full_resolution")
539         row = split.row()
540         row.active = not sima.scopes.use_full_resolution
541         row.prop(sima.scopes, "accuracy")
542
543
544 class IMAGE_PT_view_properties(bpy.types.Panel):
545     bl_space_type = 'IMAGE_EDITOR'
546     bl_region_type = 'UI'
547     bl_label = "Display"
548
549     @classmethod
550     def poll(cls, context):
551         sima = context.space_data
552         return (sima and (sima.image or sima.show_uvedit))
553
554     def draw(self, context):
555         layout = self.layout
556
557         sima = context.space_data
558         ima = sima.image
559         show_uvedit = sima.show_uvedit
560         uvedit = sima.uv_editor
561
562         split = layout.split()
563
564         col = split.column()
565         if ima:
566             col.prop(ima, "display_aspect", text="Aspect Ratio")
567
568             col = split.column()
569             col.label(text="Coordinates:")
570             col.prop(sima, "show_repeat", text="Repeat")
571             if show_uvedit:
572                 col.prop(uvedit, "show_normalized_coords", text="Normalized")
573
574         elif show_uvedit:
575             col.label(text="Coordinates:")
576             col.prop(uvedit, "show_normalized_coords", text="Normalized")
577
578         if show_uvedit:
579
580             col = layout.column()
581             col.prop(uvedit, "cursor_location")
582
583             col = layout.column()
584             col.label(text="UVs:")
585             row = col.row()
586             row.prop(uvedit, "edge_draw_type", expand=True)
587
588             split = layout.split()
589             col = split.column()
590             col.prop(uvedit, "show_smooth_edges", text="Smooth")
591             col.prop(uvedit, "show_modified_edges", text="Modified")
592             #col.prop(uvedit, "show_edges")
593             #col.prop(uvedit, "show_faces")
594
595             col = split.column()
596             col.prop(uvedit, "show_stretch", text="Stretch")
597             sub = col.column()
598             sub.active = uvedit.show_stretch
599             sub.row().prop(uvedit, "draw_stretch_type", expand=True)
600
601
602 class IMAGE_PT_paint(bpy.types.Panel):
603     bl_space_type = 'IMAGE_EDITOR'
604     bl_region_type = 'UI'
605     bl_label = "Paint"
606
607     @classmethod
608     def poll(cls, context):
609         sima = context.space_data
610         return sima.show_paint
611
612     def draw(self, context):
613         layout = self.layout
614
615         toolsettings = context.tool_settings.image_paint
616         brush = toolsettings.brush
617
618         col = layout.split().column()
619         row = col.row()
620         col.template_ID_preview(toolsettings, "brush", new="brush.add", rows=3, cols=8)
621
622         if brush:
623             col = layout.column()
624             col.template_color_wheel(brush, "color", value_slider=True)
625             col.prop(brush, "color", text="")
626
627             row = col.row(align=True)
628             row.prop(brush, "size", slider=True)
629             row.prop(brush, "use_pressure_size", toggle=True, text="")
630
631             row = col.row(align=True)
632             row.prop(brush, "strength", slider=True)
633             row.prop(brush, "use_pressure_strength", toggle=True, text="")
634
635             row = col.row(align=True)
636             row.prop(brush, "jitter", slider=True)
637             row.prop(brush, "use_pressure_jitter", toggle=True, text="")
638
639             col.prop(brush, "blend", text="Blend")
640
641             if brush.imagepaint_tool == 'CLONE':
642                 col.separator()
643                 col.prop(brush, "clone_image", text="Image")
644                 col.prop(brush, "clone_alpha", text="Alpha")
645
646
647 class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, bpy.types.Panel):
648     bl_label = "Texture"
649     bl_options = {'DEFAULT_CLOSED'}
650
651     def draw(self, context):
652         layout = self.layout
653
654         toolsettings = context.tool_settings.image_paint
655         brush = toolsettings.brush
656
657 #        tex_slot = brush.texture_slot
658
659         col = layout.column()
660
661         col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
662
663
664 class IMAGE_PT_tools_brush_tool(BrushButtonsPanel, bpy.types.Panel):
665     bl_label = "Tool"
666     bl_options = {'DEFAULT_CLOSED'}
667
668     def draw(self, context):
669         layout = self.layout
670         settings = context.tool_settings.image_paint
671         brush = settings.brush
672
673         col = layout.column(align=True)
674
675         col.prop(brush, "imagepaint_tool", expand=False, text="")
676
677         row = layout.row(align=True)
678         row.prop(brush, "use_paint_sculpt", text="", icon='SCULPTMODE_HLT')
679         row.prop(brush, "use_paint_vertex", text="", icon='VPAINT_HLT')
680         row.prop(brush, "use_paint_weight", text="", icon='WPAINT_HLT')
681         row.prop(brush, "use_paint_texture", text="", icon='TPAINT_HLT')
682
683
684 class IMAGE_PT_paint_stroke(BrushButtonsPanel, bpy.types.Panel):
685     bl_label = "Paint Stroke"
686     bl_options = {'DEFAULT_CLOSED'}
687
688     def draw(self, context):
689         layout = self.layout
690
691         toolsettings = context.tool_settings.image_paint
692         brush = toolsettings.brush
693
694         layout.prop(brush, "use_airbrush")
695         col = layout.column()
696         col.active = brush.use_airbrush
697         col.prop(brush, "rate", slider=True)
698
699         layout.prop(brush, "use_space")
700         row = layout.row(align=True)
701         row.active = brush.use_space
702         row.prop(brush, "spacing", text="Distance", slider=True)
703         row.prop(brush, "use_pressure_spacing", toggle=True, text="")
704
705         layout.prop(brush, "use_wrap")
706
707
708 class IMAGE_PT_paint_curve(BrushButtonsPanel, bpy.types.Panel):
709     bl_label = "Paint Curve"
710     bl_options = {'DEFAULT_CLOSED'}
711
712     def draw(self, context):
713         layout = self.layout
714
715         toolsettings = context.tool_settings.image_paint
716         brush = toolsettings.brush
717
718         layout.template_curve_mapping(brush, "curve")
719
720         row = layout.row(align=True)
721         row.operator("brush.curve_preset", icon="SMOOTHCURVE", text="").shape = 'SMOOTH'
722         row.operator("brush.curve_preset", icon="SPHERECURVE", text="").shape = 'ROUND'
723         row.operator("brush.curve_preset", icon="ROOTCURVE", text="").shape = 'ROOT'
724         row.operator("brush.curve_preset", icon="SHARPCURVE", text="").shape = 'SHARP'
725         row.operator("brush.curve_preset", icon="LINCURVE", text="").shape = 'LINE'
726         row.operator("brush.curve_preset", icon="NOCURVE", text="").shape = 'MAX'
727
728
729 def register():
730     bpy.utils.register_module(__name__)
731
732
733 def unregister():
734     bpy.utils.unregister_module(__name__)
735
736 if __name__ == "__main__":
737     register()