bcb227b55ec34e017f7ee3481de3d8201e416043
[blender-staging.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") # Numpad /
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_enums("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_HT_header(bpy.types.Header):
256     bl_space_type = 'IMAGE_EDITOR'
257
258     def draw(self, context):
259         layout = self.layout
260
261         sima = context.space_data
262         ima = sima.image
263         iuser = sima.image_user
264         toolsettings = context.tool_settings
265
266         show_render = sima.show_render
267         # show_paint = sima.show_paint
268         show_uvedit = sima.show_uvedit
269
270         row = layout.row(align=True)
271         row.template_header()
272
273         # menus
274         if context.area.show_menus:
275             sub = row.row(align=True)
276             sub.menu("IMAGE_MT_view")
277
278             if show_uvedit:
279                 sub.menu("IMAGE_MT_select")
280
281             if ima and ima.is_dirty:
282                 sub.menu("IMAGE_MT_image", text="Image*")
283             else:
284                 sub.menu("IMAGE_MT_image", text="Image")
285
286             if show_uvedit:
287                 sub.menu("IMAGE_MT_uvs")
288
289         layout.template_ID(sima, "image", new="image.new")
290         if not show_render:
291             layout.prop(sima, "use_image_pin", text="")
292
293         # uv editing
294         if show_uvedit:
295             uvedit = sima.uv_editor
296
297             layout.prop(uvedit, "pivot_point", text="", icon_only=True)
298             layout.prop(toolsettings, "use_uv_select_sync", text="")
299
300             if toolsettings.use_uv_select_sync:
301                 row = layout.row(align=True)
302                 row.prop(toolsettings, "mesh_select_mode", text="", index=0, icon='VERTEXSEL')
303                 row.prop(toolsettings, "mesh_select_mode", text="", index=1, icon='EDGESEL')
304                 row.prop(toolsettings, "mesh_select_mode", text="", index=2, icon='FACESEL')
305             else:
306                 layout.prop(toolsettings, "uv_select_mode", text="", expand=True)
307                 layout.prop(uvedit, "sticky_select_mode", text="", icon_only=True)
308
309             row = layout.row(align=True)
310             row.prop(toolsettings, "proportional_edit", text="", icon_only=True)
311             if toolsettings.proportional_edit != 'DISABLED':
312                 row.prop(toolsettings, "proportional_edit_falloff", text="", icon_only=True)
313
314             row = layout.row(align=True)
315             row.prop(toolsettings, "use_snap", text="")
316             row.prop(toolsettings, "snap_element", text="", icon_only=True)
317
318             # mesh = context.edit_object.data
319             # row.prop_object(mesh, "active_uv_layer", mesh, "uv_textures")
320
321         if ima:
322             # layers
323             layout.template_image_layers(ima, iuser)
324
325             # painting
326             layout.prop(sima, "use_image_paint", text="")
327
328             # draw options
329             row = layout.row(align=True)
330             row.prop(sima, "draw_channels", text="", expand=True)
331
332             row = layout.row(align=True)
333             if ima.type == 'COMPOSITE':
334                 row.operator("image.record_composite", icon='REC')
335             if ima.type == 'COMPOSITE' and ima.source in ('MOVIE', 'SEQUENCE'):
336                 row.operator("image.play_composite", icon='PLAY')
337
338         if show_uvedit or sima.use_image_paint:
339             layout.prop(sima, "use_realtime_update", text="", icon_only=True, icon='LOCKED')
340
341
342 class IMAGE_PT_image_properties(bpy.types.Panel):
343     bl_space_type = 'IMAGE_EDITOR'
344     bl_region_type = 'UI'
345     bl_label = "Image"
346
347     @classmethod
348     def poll(cls, context):
349         sima = context.space_data
350         return (sima.image)
351
352     def draw(self, context):
353         layout = self.layout
354
355         sima = context.space_data
356         # ima = sima.image
357         iuser = sima.image_user
358
359         layout.template_image(sima, "image", iuser)
360
361
362 class IMAGE_PT_game_properties(bpy.types.Panel):
363     bl_space_type = 'IMAGE_EDITOR'
364     bl_region_type = 'UI'
365     bl_label = "Game Properties"
366
367     @classmethod
368     def poll(cls, context):
369         rd = context.scene.render
370         sima = context.space_data
371         return (sima and sima.image) and (rd.engine == 'BLENDER_GAME')
372
373     def draw(self, context):
374         layout = self.layout
375
376         sima = context.space_data
377         ima = sima.image
378
379         split = layout.split()
380
381         col = split.column()
382
383         sub = col.column(align=True)
384         sub.prop(ima, "animated")
385
386         subsub = sub.column()
387         subsub.active = ima.animated
388         subsub.prop(ima, "animation_start", text="Start")
389         subsub.prop(ima, "animation_end", text="End")
390         subsub.prop(ima, "animation_speed", text="Speed")
391
392         col.prop(ima, "tiles")
393         sub = col.column(align=True)
394         sub.active = ima.tiles or ima.animated
395         sub.prop(ima, "tiles_x", text="X")
396         sub.prop(ima, "tiles_y", text="Y")
397
398         col = split.column()
399         col.label(text="Clamp:")
400         col.prop(ima, "clamp_x", text="X")
401         col.prop(ima, "clamp_y", text="Y")
402         col.separator()
403         col.prop(ima, "mapping", expand=True)
404
405
406 class IMAGE_PT_view_histogram(bpy.types.Panel):
407     bl_space_type = 'IMAGE_EDITOR'
408     bl_region_type = 'PREVIEW'
409     bl_label = "Histogram"
410
411     @classmethod
412     def poll(cls, context):
413         sima = context.space_data
414         return (sima and sima.image)
415
416     def draw(self, context):
417         layout = self.layout
418
419         sima = context.space_data
420
421         layout.template_histogram(sima.scopes, "histogram")
422         layout.prop(sima.scopes.histogram, "mode", icon_only=True)
423
424
425 class IMAGE_PT_view_waveform(bpy.types.Panel):
426     bl_space_type = 'IMAGE_EDITOR'
427     bl_region_type = 'PREVIEW'
428     bl_label = "Waveform"
429
430     @classmethod
431     def poll(cls, context):
432         sima = context.space_data
433         return (sima and sima.image)
434
435     def draw(self, context):
436         layout = self.layout
437
438         sima = context.space_data
439         layout.template_waveform(sima, "scopes")
440         sub = layout.row().split(percentage=0.75)
441         sub.prop(sima.scopes, "waveform_alpha")
442         sub.prop(sima.scopes, "waveform_mode", text="", icon_only=True)
443
444
445 class IMAGE_PT_view_vectorscope(bpy.types.Panel):
446     bl_space_type = 'IMAGE_EDITOR'
447     bl_region_type = 'PREVIEW'
448     bl_label = "Vectorscope"
449
450     @classmethod
451     def poll(cls, context):
452         sima = context.space_data
453         return (sima and sima.image)
454
455     def draw(self, context):
456         layout = self.layout
457
458         sima = context.space_data
459         layout.template_vectorscope(sima, "scopes")
460         layout.prop(sima.scopes, "vectorscope_alpha")
461
462
463 class IMAGE_PT_sample_line(bpy.types.Panel):
464     bl_space_type = 'IMAGE_EDITOR'
465     bl_region_type = 'PREVIEW'
466     bl_label = "Sample Line"
467
468     @classmethod
469     def poll(cls, context):
470         sima = context.space_data
471         return (sima and sima.image)
472
473     def draw(self, context):
474         layout = self.layout
475         layout.operator("image.sample_line")
476         sima = context.space_data
477         layout.template_histogram(sima, "sample_histogram")
478         layout.prop(sima.sample_histogram, "mode")
479
480
481 class IMAGE_PT_scope_sample(bpy.types.Panel):
482     bl_space_type = 'IMAGE_EDITOR'
483     bl_region_type = 'PREVIEW'
484     bl_label = "Scope Samples"
485
486     @classmethod
487     def poll(cls, context):
488         sima = context.space_data
489         return sima
490
491     def draw(self, context):
492         layout = self.layout
493         sima = context.space_data
494         split = layout.split()
495         row = split.row()
496         row.prop(sima.scopes, "use_full_resolution")
497         row = split.row()
498         row.active = not sima.scopes.use_full_resolution
499         row.prop(sima.scopes, "accuracy")
500
501
502 class IMAGE_PT_view_properties(bpy.types.Panel):
503     bl_space_type = 'IMAGE_EDITOR'
504     bl_region_type = 'UI'
505     bl_label = "Display"
506
507     @classmethod
508     def poll(cls, context):
509         sima = context.space_data
510         return (sima and (sima.image or sima.show_uvedit))
511
512     def draw(self, context):
513         layout = self.layout
514
515         sima = context.space_data
516         ima = sima.image
517         show_uvedit = sima.show_uvedit
518         uvedit = sima.uv_editor
519
520         split = layout.split()
521
522         col = split.column()
523         if ima:
524             col.prop(ima, "display_aspect", text="Aspect Ratio")
525
526             col = split.column()
527             col.label(text="Coordinates:")
528             col.prop(sima, "show_repeat", text="Repeat")
529             if show_uvedit:
530                 col.prop(uvedit, "show_normalized_coords", text="Normalized")
531
532         elif show_uvedit:
533             col.label(text="Coordinates:")
534             col.prop(uvedit, "show_normalized_coords", text="Normalized")
535
536         if show_uvedit:
537
538             col = layout.column()
539             col.prop(uvedit, "cursor_location")
540
541             col = layout.column()
542             col.label(text="UVs:")
543             row = col.row()
544             row.prop(uvedit, "edge_draw_type", expand=True)
545
546             split = layout.split()
547             col = split.column()
548             col.prop(uvedit, "show_smooth_edges", text="Smooth")
549             col.prop(uvedit, "show_modified_edges", text="Modified")
550             #col.prop(uvedit, "show_edges")
551             #col.prop(uvedit, "show_faces")
552
553             col = split.column()
554             col.prop(uvedit, "show_stretch", text="Stretch")
555             sub = col.column()
556             sub.active = uvedit.show_stretch
557             sub.row().prop(uvedit, "draw_stretch_type", expand=True)
558
559
560 class IMAGE_PT_paint(bpy.types.Panel):
561     bl_space_type = 'IMAGE_EDITOR'
562     bl_region_type = 'UI'
563     bl_label = "Paint"
564
565     @classmethod
566     def poll(cls, context):
567         sima = context.space_data
568         return sima.show_paint
569
570     def draw(self, context):
571         layout = self.layout
572
573         toolsettings = context.tool_settings.image_paint
574         brush = toolsettings.brush
575
576         col = layout.split().column()
577         row = col.row()
578         col.template_ID_preview(toolsettings, "brush", new="brush.add", rows=3, cols=8)
579
580         if brush:
581             col = layout.column()
582             col.template_color_wheel(brush, "color", value_slider=True)
583             col.prop(brush, "color", text="")
584
585             row = col.row(align=True)
586             row.prop(brush, "size", slider=True)
587             row.prop(brush, "use_pressure_size", toggle=True, text="")
588
589             row = col.row(align=True)
590             row.prop(brush, "strength", slider=True)
591             row.prop(brush, "use_pressure_strength", toggle=True, text="")
592
593             row = col.row(align=True)
594             row.prop(brush, "jitter", slider=True)
595             row.prop(brush, "use_pressure_jitter", toggle=True, text="")
596
597             col.prop(brush, "blend", text="Blend")
598
599             if brush.imagepaint_tool == 'CLONE':
600                 col.separator()
601                 col.prop(brush, "clone_image", text="Image")
602                 col.prop(brush, "clone_alpha", text="Alpha")
603
604
605 class IMAGE_PT_tools_brush_texture(BrushButtonsPanel, bpy.types.Panel):
606     bl_label = "Texture"
607     bl_default_closed = True
608
609     def draw(self, context):
610         layout = self.layout
611
612         toolsettings = context.tool_settings.image_paint
613         brush = toolsettings.brush
614
615 #        tex_slot = brush.texture_slot
616
617         col = layout.column()
618
619         col.template_ID_preview(brush, "texture", new="texture.new", rows=3, cols=8)
620
621
622 class IMAGE_PT_paint_stroke(BrushButtonsPanel, bpy.types.Panel):
623     bl_label = "Paint Stroke"
624     bl_default_closed = True
625
626     def draw(self, context):
627         layout = self.layout
628
629         toolsettings = context.tool_settings.image_paint
630         brush = toolsettings.brush
631
632         layout.prop(brush, "use_airbrush")
633         col = layout.column()
634         col.active = brush.use_airbrush
635         col.prop(brush, "rate", slider=True)
636
637         layout.prop(brush, "use_space")
638         row = layout.row(align=True)
639         row.active = brush.use_space
640         row.prop(brush, "spacing", text="Distance", slider=True)
641         row.prop(brush, "use_pressure_spacing", toggle=True, text="")
642
643         layout.prop(brush, "use_wrap")
644
645
646 class IMAGE_PT_paint_curve(BrushButtonsPanel, bpy.types.Panel):
647     bl_label = "Paint Curve"
648     bl_default_closed = True
649
650     def draw(self, context):
651         layout = self.layout
652
653         toolsettings = context.tool_settings.image_paint
654         brush = toolsettings.brush
655
656         layout.template_curve_mapping(brush, "curve")
657
658         row = layout.row(align=True)
659         row.operator("brush.curve_preset", icon="SMOOTHCURVE", text="").shape = 'SMOOTH'
660         row.operator("brush.curve_preset", icon="SPHERECURVE", text="").shape = 'ROUND'
661         row.operator("brush.curve_preset", icon="ROOTCURVE", text="").shape = 'ROOT'
662         row.operator("brush.curve_preset", icon="SHARPCURVE", text="").shape = 'SHARP'
663         row.operator("brush.curve_preset", icon="LINCURVE", text="").shape = 'LINE'
664         row.operator("brush.curve_preset", icon="NOCURVE", text="").shape = 'MAX'
665
666 def register():
667     pass
668
669
670 def unregister():
671     pass
672
673 if __name__ == "__main__":
674     register()