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