4c72e1ccb10034f778f8a401741994c0d8631342
[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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21
22 narrowui = 180
23
24
25 class IMAGE_MT_view(bpy.types.Menu):
26     bl_label = "View"
27
28     def draw(self, context):
29         layout = self.layout
30
31         sima = context.space_data
32         # uv = sima.uv_editor
33         settings = context.tool_settings
34
35         show_uvedit = sima.show_uvedit
36
37         layout.operator("image.properties", icon='ICON_MENU_PANEL')
38
39         layout.separator()
40
41         layout.prop(sima, "update_automatically")
42         if show_uvedit:
43             layout.prop(settings, "uv_local_view") # Numpad /
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_float("image.view_zoom_ratio", "ratio", a / b, text=text)
57
58         layout.separator()
59
60         if show_uvedit:
61             layout.operator("image.view_selected")
62
63         layout.operator("image.view_all")
64         layout.operator("screen.screen_full_area")
65
66
67 class IMAGE_MT_select(bpy.types.Menu):
68     bl_label = "Select"
69
70     def draw(self, context):
71         layout = self.layout
72
73         layout.operator("uv.select_border")
74         layout.operator_boolean("uv.select_border", "pinned", True)
75
76         layout.separator()
77
78         layout.operator("uv.select_all_toggle")
79         layout.operator("uv.select_inverse")
80         layout.operator("uv.unlink_selection")
81
82         layout.separator()
83
84         layout.operator("uv.select_pinned")
85         layout.operator("uv.select_linked")
86
87
88 class IMAGE_MT_image(bpy.types.Menu):
89     bl_label = "Image"
90
91     def draw(self, context):
92         layout = self.layout
93
94         sima = context.space_data
95         ima = sima.image
96
97         layout.operator("image.new")
98         layout.operator("image.open")
99
100         show_render = sima.show_render
101
102         if ima:
103             if not show_render:
104                 layout.operator("image.replace")
105                 layout.operator("image.reload")
106
107             layout.operator("image.save")
108             layout.operator("image.save_as")
109
110             if ima.source == 'SEQUENCE':
111                 layout.operator("image.save_sequence")
112
113             if not show_render:
114                 layout.separator()
115
116                 if ima.packed_file:
117                     layout.operator("image.unpack")
118                 else:
119                     layout.operator("image.pack")
120
121                 # only for dirty && specific image types, perhaps
122                 # this could be done in operator poll too
123                 if ima.dirty:
124                     if ima.source in ('FILE', 'GENERATED') and ima.type != 'MULTILAYER':
125                         layout.operator_boolean("image.pack", "as_png", True, text="Pack As PNG")
126
127             layout.separator()
128
129             layout.prop(sima, "image_painting")
130
131
132 class IMAGE_MT_uvs_showhide(bpy.types.Menu):
133     bl_label = "Show/Hide Faces"
134
135     def draw(self, context):
136         layout = self.layout
137
138         layout.operator("uv.reveal")
139         layout.operator("uv.hide")
140         layout.operator_boolean("uv.hide", "unselected", True)
141
142
143 class IMAGE_MT_uvs_transform(bpy.types.Menu):
144     bl_label = "Transform"
145
146     def draw(self, context):
147         layout = self.layout
148
149         layout.operator("tfm.translate")
150         layout.operator("tfm.rotate")
151         layout.operator("tfm.resize")
152
153
154 class IMAGE_MT_uvs_mirror(bpy.types.Menu):
155     bl_label = "Mirror"
156
157     def draw(self, context):
158         layout = self.layout
159         layout.operator_context = 'EXEC_REGION_WIN'
160
161         props = layout.operator("tfm.mirror", text="X Axis", properties=True)
162         props.constraint_axis[0] = True
163
164         props = layout.operator("tfm.mirror", text="Y Axis", properties=True)
165         props.constraint_axis[1] = True
166
167
168 class IMAGE_MT_uvs_weldalign(bpy.types.Menu):
169     bl_label = "Weld/Align"
170
171     def draw(self, context):
172         layout = self.layout
173
174         layout.operator("uv.weld") # W, 1
175         layout.operator_enums("uv.align", "axis") # W, 2/3/4
176
177
178 class IMAGE_MT_uvs(bpy.types.Menu):
179     bl_label = "UVs"
180
181     def draw(self, context):
182         layout = self.layout
183
184         sima = context.space_data
185         uv = sima.uv_editor
186         settings = context.tool_settings
187
188         layout.prop(uv, "snap_to_pixels")
189         layout.prop(uv, "constrain_to_image_bounds")
190
191         layout.separator()
192
193         layout.prop(uv, "live_unwrap")
194         layout.operator("uv.unwrap")
195         layout.operator_boolean("uv.pin", "clear", True, text="Unpin")
196         layout.operator("uv.pin")
197
198         layout.separator()
199
200         layout.operator("uv.pack_islands")
201         layout.operator("uv.average_islands_scale")
202         layout.operator("uv.minimize_stretch")
203         layout.operator("uv.stitch")
204
205         layout.separator()
206
207         layout.menu("IMAGE_MT_uvs_transform")
208         layout.menu("IMAGE_MT_uvs_mirror")
209         layout.menu("IMAGE_MT_uvs_weldalign")
210
211         layout.separator()
212
213         layout.prop_menu_enum(settings, "proportional_editing")
214         layout.prop_menu_enum(settings, "proportional_editing_falloff")
215
216         layout.separator()
217
218         layout.menu("IMAGE_MT_uvs_showhide")
219
220
221 class IMAGE_HT_header(bpy.types.Header):
222     bl_space_type = 'IMAGE_EDITOR'
223
224     def draw(self, context):
225         layout = self.layout
226
227         sima = context.space_data
228         ima = sima.image
229         iuser = sima.image_user
230         settings = context.tool_settings
231
232         # show_render = sima.show_render
233         # show_paint = sima.show_paint
234         show_uvedit = sima.show_uvedit
235
236         row = layout.row(align=True)
237         row.template_header()
238
239         # menus
240         if context.area.show_menus:
241             sub = row.row(align=True)
242             sub.menu("IMAGE_MT_view")
243
244             if show_uvedit:
245                 sub.menu("IMAGE_MT_select")
246
247             if ima and ima.dirty:
248                 sub.menu("IMAGE_MT_image", text="Image*")
249             else:
250                 sub.menu("IMAGE_MT_image", text="Image")
251
252             if show_uvedit:
253                 sub.menu("IMAGE_MT_uvs")
254
255         layout.template_ID(sima, "image", new="image.new")
256
257         # uv editing
258         if show_uvedit:
259             uvedit = sima.uv_editor
260
261             layout.prop(uvedit, "pivot", text="", icon_only=True)
262             layout.prop(settings, "uv_sync_selection", text="")
263
264             if settings.uv_sync_selection:
265                 layout.prop(settings, "mesh_selection_mode", text="", expand=True)
266             else:
267                 layout.prop(settings, "uv_selection_mode", text="", expand=True)
268                 layout.prop(uvedit, "sticky_selection_mode", text="", icon_only=True)
269
270             row = layout.row(align=True)
271             row.prop(settings, "snap", text="")
272             if settings.snap:
273                 row.prop(settings, "snap_mode", text="")
274
275             # mesh = context.edit_object.data
276             # row.prop_pointer(mesh, "active_uv_layer", mesh, "uv_textures")
277
278         if ima:
279             # layers
280             layout.template_image_layers(ima, iuser)
281
282             # painting
283             layout.prop(sima, "image_painting", text="")
284
285             # draw options
286             row = layout.row(align=True)
287             row.prop(sima, "draw_channels", text="", expand=True)
288
289             row = layout.row(align=True)
290             if ima.type == 'COMPOSITE':
291                 row.operator("image.record_composite", icon='ICON_REC')
292             if ima.type == 'COMPOSITE' and ima.source in ('MOVIE', 'SEQUENCE'):
293                 row.operator("image.play_composite", icon='ICON_PLAY')
294
295         if show_uvedit or sima.image_painting:
296             layout.prop(sima, "update_automatically", text="")
297
298
299 class IMAGE_PT_image_properties(bpy.types.Panel):
300     bl_space_type = 'IMAGE_EDITOR'
301     bl_region_type = 'UI'
302     bl_label = "Image"
303
304     def poll(self, context):
305         sima = context.space_data
306         return (sima.image)
307
308     def draw(self, context):
309         layout = self.layout
310
311         sima = context.space_data
312         # ima = sima.image
313         iuser = sima.image_user
314
315         layout.template_image(sima, "image", iuser, compact=True)
316
317
318 class IMAGE_PT_game_properties(bpy.types.Panel):
319     bl_space_type = 'IMAGE_EDITOR'
320     bl_region_type = 'UI'
321     bl_label = "Game Properties"
322
323     def poll(self, context):
324         rd = context.scene.render_data
325         sima = context.space_data
326         return (sima and sima.image) and (rd.engine == 'BLENDER_GAME')
327
328     def draw(self, context):
329         layout = self.layout
330
331         sima = context.space_data
332         ima = sima.image
333         wide_ui = context.region.width > narrowui
334
335         split = layout.split()
336
337         col = split.column()
338
339         sub = col.column(align=True)
340         sub.prop(ima, "animated")
341
342         subsub = sub.column()
343         subsub.active = ima.animated
344         subsub.prop(ima, "animation_start", text="Start")
345         subsub.prop(ima, "animation_end", text="End")
346         subsub.prop(ima, "animation_speed", text="Speed")
347
348         col.prop(ima, "tiles")
349         sub = col.column(align=True)
350         sub.active = ima.tiles or ima.animated
351         sub.prop(ima, "tiles_x", text="X")
352         sub.prop(ima, "tiles_y", text="Y")
353
354         if wide_ui:
355             col = split.column()
356         col.label(text="Clamp:")
357         col.prop(ima, "clamp_x", text="X")
358         col.prop(ima, "clamp_y", text="Y")
359         col.separator()
360         col.prop(ima, "mapping", expand=True)
361
362
363 class IMAGE_PT_view_properties(bpy.types.Panel):
364     bl_space_type = 'IMAGE_EDITOR'
365     bl_region_type = 'UI'
366     bl_label = "Display"
367
368     def poll(self, context):
369         sima = context.space_data
370         return (sima and (sima.image or sima.show_uvedit))
371
372     def draw(self, context):
373         layout = self.layout
374
375         sima = context.space_data
376         ima = sima.image
377         show_uvedit = sima.show_uvedit
378         uvedit = sima.uv_editor
379         wide_ui = context.region.width > narrowui
380
381         split = layout.split()
382
383         col = split.column()
384         if ima:
385             col.prop(ima, "display_aspect", text="Aspect Ratio")
386
387             if wide_ui:
388                 col = split.column()
389             col.label(text="Coordinates:")
390             col.prop(sima, "draw_repeated", text="Repeat")
391             if show_uvedit:
392                 col.prop(uvedit, "normalized_coordinates", text="Normalized")
393         elif show_uvedit:
394             col.label(text="Coordinates:")
395             col.prop(uvedit, "normalized_coordinates", text="Normalized")
396
397         if show_uvedit:
398
399             col = layout.column()
400             col.label(text="UVs:")
401             row = col.row()
402             if wide_ui:
403                 row.prop(uvedit, "edge_draw_type", expand=True)
404             else:
405                 row.prop(uvedit, "edge_draw_type", text="")
406
407             split = layout.split()
408             col = split.column()
409             col.prop(uvedit, "draw_smooth_edges", text="Smooth")
410             col.prop(uvedit, "draw_modified_edges", text="Modified")
411             #col.prop(uvedit, "draw_edges")
412             #col.prop(uvedit, "draw_faces")
413
414             if wide_ui:
415                 col = split.column()
416             col.prop(uvedit, "draw_stretch", text="Stretch")
417             sub = col.column()
418             sub.active = uvedit.draw_stretch
419             sub.row().prop(uvedit, "draw_stretch_type", expand=True)
420
421
422 class IMAGE_PT_paint(bpy.types.Panel):
423     bl_space_type = 'IMAGE_EDITOR'
424     bl_region_type = 'UI'
425     bl_label = "Paint"
426
427     def poll(self, context):
428         sima = context.space_data
429         return sima.show_paint
430
431     def draw(self, context):
432         layout = self.layout
433
434         settings = context.tool_settings.image_paint
435         brush = settings.brush
436         wide_ui = context.region.width > narrowui
437
438         col = layout.split().column()
439         row = col.row()
440         row.template_list(settings, "brushes", settings, "active_brush_index", rows=2)
441
442         col.template_ID(settings, "brush", new="brush.add")
443
444         if wide_ui:
445             sub = layout.row(align=True)
446         else:
447             sub = layout.column(align=True)
448         sub.item_enumR(settings, "tool", 'DRAW')
449         sub.item_enumR(settings, "tool", 'SOFTEN')
450         sub.item_enumR(settings, "tool", 'CLONE')
451         sub.item_enumR(settings, "tool", 'SMEAR')
452
453         if brush:
454             col = layout.column()
455             col.prop(brush, "color", text="")
456
457             row = col.row(align=True)
458             row.prop(brush, "size", slider=True)
459             row.prop(brush, "use_size_pressure", toggle=True, text="")
460
461             row = col.row(align=True)
462             row.prop(brush, "strength", slider=True)
463             row.prop(brush, "use_strength_pressure", toggle=True, text="")
464
465             row = col.row(align=True)
466             row.prop(brush, "jitter", slider=True)
467             row.prop(brush, "use_jitter_pressure", toggle=True, text="")
468
469             col.prop(brush, "blend", text="Blend")
470
471
472 class IMAGE_PT_paint_stroke(bpy.types.Panel):
473     bl_space_type = 'IMAGE_EDITOR'
474     bl_region_type = 'UI'
475     bl_label = "Paint Stroke"
476     bl_default_closed = True
477
478     def poll(self, context):
479         sima = context.space_data
480         settings = context.tool_settings.image_paint
481         return sima.show_paint and settings.brush
482
483     def draw(self, context):
484         layout = self.layout
485
486         settings = context.tool_settings.image_paint
487         brush = settings.brush
488
489         layout.prop(brush, "use_airbrush")
490         col = layout.column()
491         col.active = brush.use_airbrush
492         col.prop(brush, "rate", slider=True)
493
494         layout.prop(brush, "use_space")
495         row = layout.row(align=True)
496         row.active = brush.use_space
497         row.prop(brush, "spacing", text="Distance", slider=True)
498         row.prop(brush, "use_spacing_pressure", toggle=True, text="")
499
500
501 class IMAGE_PT_paint_curve(bpy.types.Panel):
502     bl_space_type = 'IMAGE_EDITOR'
503     bl_region_type = 'UI'
504     bl_label = "Paint Curve"
505     bl_default_closed = True
506
507     def poll(self, context):
508         sima = context.space_data
509         settings = context.tool_settings.image_paint
510         return sima.show_paint and settings.brush
511
512     def draw(self, context):
513         layout = self.layout
514
515         settings = context.tool_settings.image_paint
516         brush = settings.brush
517
518         layout.template_curve_mapping(brush, "curve")
519         layout.operator_menu_enum("brush.curve_preset", property="shape")
520
521 bpy.types.register(IMAGE_MT_view)
522 bpy.types.register(IMAGE_MT_select)
523 bpy.types.register(IMAGE_MT_image)
524 bpy.types.register(IMAGE_MT_uvs_showhide)
525 bpy.types.register(IMAGE_MT_uvs_transform)
526 bpy.types.register(IMAGE_MT_uvs_mirror)
527 bpy.types.register(IMAGE_MT_uvs_weldalign)
528 bpy.types.register(IMAGE_MT_uvs)
529 bpy.types.register(IMAGE_HT_header)
530 bpy.types.register(IMAGE_PT_image_properties)
531 bpy.types.register(IMAGE_PT_paint)
532 bpy.types.register(IMAGE_PT_paint_stroke)
533 bpy.types.register(IMAGE_PT_paint_curve)
534 bpy.types.register(IMAGE_PT_game_properties)
535 bpy.types.register(IMAGE_PT_view_properties)