Add ctrl-click rename to most lists in Blender UI and templates/examples.
[blender.git] / release / scripts / startup / bl_ui / properties_texture.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 Menu, Panel, UIList
22
23 from bpy.types import (Brush,
24                        Lamp,
25                        Material,
26                        Object,
27                        ParticleSettings,
28                        Texture,
29                        World)
30
31 from rna_prop_ui import PropertyPanel
32
33 from bl_ui.properties_paint_common import brush_texture_settings
34
35
36 class TEXTURE_MT_specials(Menu):
37     bl_label = "Texture Specials"
38     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
39
40     def draw(self, context):
41         layout = self.layout
42
43         layout.operator("texture.slot_copy", icon='COPYDOWN')
44         layout.operator("texture.slot_paste", icon='PASTEDOWN')
45
46
47 class TEXTURE_MT_envmap_specials(Menu):
48     bl_label = "Environment Map Specials"
49     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
50
51     def draw(self, context):
52         layout = self.layout
53
54         layout.operator("texture.envmap_save", icon='IMAGEFILE')
55         layout.operator("texture.envmap_clear", icon='FILE_REFRESH')
56         layout.operator("texture.envmap_clear_all", icon='FILE_REFRESH')
57
58
59 class TEXTURE_UL_texslots(UIList):
60     def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
61         # assert(isinstance(item, bpy.types.MaterialTextureSlot)
62         ma = data
63         slot = item
64         tex = slot.texture if slot else None
65         if self.layout_type in {'DEFAULT', 'COMPACT'}:
66             if tex:
67                 layout.prop(tex, "name", text="", emboss=False, icon_value=icon)
68             else:
69                 layout.label(text="", icon_value=icon)
70             if tex and isinstance(item, bpy.types.MaterialTextureSlot):
71                 layout.prop(ma, "use_textures", text="", index=index)
72         elif self.layout_type in {'GRID'}:
73             layout.alignment = 'CENTER'
74             layout.label(text="", icon_value=icon)
75
76
77 from bl_ui.properties_material import active_node_mat
78
79
80 def context_tex_datablock(context):
81     idblock = context.material
82     if idblock:
83         return active_node_mat(idblock)
84
85     idblock = context.lamp
86     if idblock:
87         return idblock
88
89     idblock = context.world
90     if idblock:
91         return idblock
92
93     idblock = context.brush
94     if idblock:
95         return idblock
96
97     if context.particle_system:
98         idblock = context.particle_system.settings
99
100     return idblock
101
102
103 def id_tex_datablock(bid):
104     if isinstance(bid, Object):
105         if bid.type == 'LAMP':
106             return bid.data
107         return bid.active_material
108
109     return bid
110
111
112 class TextureButtonsPanel():
113     bl_space_type = 'PROPERTIES'
114     bl_region_type = 'WINDOW'
115     bl_context = "texture"
116
117     @classmethod
118     def poll(cls, context):
119         tex = context.texture
120         return tex and (tex.type != 'NONE' or tex.use_nodes) and (context.scene.render.engine in cls.COMPAT_ENGINES)
121
122
123 class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
124     bl_label = ""
125     bl_options = {'HIDE_HEADER'}
126     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
127
128     @classmethod
129     def poll(cls, context):
130         engine = context.scene.render.engine
131         #if not (hasattr(context, "texture_slot") or hasattr(context, "texture_node")):
132             #return False
133         return ((context.material or
134                  context.world or
135                  context.lamp or
136                  context.texture or
137                  context.particle_system or
138                  isinstance(context.space_data.pin_id, ParticleSettings) or
139                  context.texture_user) and
140                 (engine in cls.COMPAT_ENGINES))
141
142     def draw(self, context):
143         layout = self.layout
144
145         slot = getattr(context, "texture_slot", None)
146         node = getattr(context, "texture_node", None)
147         space = context.space_data
148         tex = context.texture
149         idblock = context_tex_datablock(context)
150         pin_id = space.pin_id
151
152         space.use_limited_texture_context = True
153
154         if space.use_pin_id and not isinstance(pin_id, Texture):
155             idblock = id_tex_datablock(pin_id)
156             pin_id = None
157
158         if not space.use_pin_id:
159             layout.prop(space, "texture_context", expand=True)
160             pin_id = None
161
162         if space.texture_context == 'OTHER':
163             if not pin_id:
164                 layout.template_texture_user()
165             user = context.texture_user
166             if user or pin_id:
167                 layout.separator()
168
169                 split = layout.split(percentage=0.65)
170                 col = split.column()
171
172                 if pin_id:
173                     col.template_ID(space, "pin_id")
174                 else:
175                     propname = context.texture_user_property.identifier
176                     col.template_ID(user, propname, new="texture.new")
177
178                 if tex:
179                     split = layout.split(percentage=0.2)
180                     if tex.use_nodes:
181                         if slot:
182                             split.label(text="Output:")
183                             split.prop(slot, "output_node", text="")
184                     else:
185                         split.label(text="Type:")
186                         split.prop(tex, "type", text="")
187             return
188
189         tex_collection = (pin_id is None) and (node is None) and (not isinstance(idblock, Brush))
190
191         if tex_collection:
192             row = layout.row()
193
194             row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots", idblock, "active_texture_index", rows=2)
195
196             col = row.column(align=True)
197             col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
198             col.operator("texture.slot_move", text="", icon='TRIA_DOWN').type = 'DOWN'
199             col.menu("TEXTURE_MT_specials", icon='DOWNARROW_HLT', text="")
200
201         if tex_collection:
202             layout.template_ID(idblock, "active_texture", new="texture.new")
203         elif node:
204             layout.template_ID(node, "texture", new="texture.new")
205         elif idblock:
206             layout.template_ID(idblock, "texture", new="texture.new")
207
208         if pin_id:
209             layout.template_ID(space, "pin_id")
210
211         if tex:
212             split = layout.split(percentage=0.2)
213             if tex.use_nodes:
214                 if slot:
215                     split.label(text="Output:")
216                     split.prop(slot, "output_node", text="")
217             else:
218                 split.label(text="Type:")
219                 split.prop(tex, "type", text="")
220
221
222 class TEXTURE_PT_preview(TextureButtonsPanel, Panel):
223     bl_label = "Preview"
224     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
225
226     def draw(self, context):
227         layout = self.layout
228
229         tex = context.texture
230         slot = getattr(context, "texture_slot", None)
231         idblock = context_tex_datablock(context)
232
233         if idblock:
234             layout.template_preview(tex, parent=idblock, slot=slot)
235         else:
236             layout.template_preview(tex, slot=slot)
237
238         #Show Alpha Button for Brush Textures, see #29502
239         if context.space_data.texture_context == 'BRUSH':
240             layout.prop(tex, "use_preview_alpha")
241
242
243 class TEXTURE_PT_colors(TextureButtonsPanel, Panel):
244     bl_label = "Colors"
245     bl_options = {'DEFAULT_CLOSED'}
246     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
247
248     def draw(self, context):
249         layout = self.layout
250
251         tex = context.texture
252
253         layout.prop(tex, "use_color_ramp", text="Ramp")
254         if tex.use_color_ramp:
255             layout.template_color_ramp(tex, "color_ramp", expand=True)
256
257         split = layout.split()
258
259         col = split.column()
260         col.label(text="RGB Multiply:")
261         sub = col.column(align=True)
262         sub.prop(tex, "factor_red", text="R")
263         sub.prop(tex, "factor_green", text="G")
264         sub.prop(tex, "factor_blue", text="B")
265
266         col = split.column()
267         col.label(text="Adjust:")
268         col.prop(tex, "intensity")
269         col.prop(tex, "contrast")
270         col.prop(tex, "saturation")
271
272 # Texture Slot Panels #
273
274
275 class TextureSlotPanel(TextureButtonsPanel):
276     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
277
278     @classmethod
279     def poll(cls, context):
280         if not hasattr(context, "texture_slot"):
281             return False
282
283         engine = context.scene.render.engine
284         return TextureButtonsPanel.poll(cls, context) and (engine in cls.COMPAT_ENGINES)
285
286
287 # Texture Type Panels #
288
289
290 class TextureTypePanel(TextureButtonsPanel):
291
292     @classmethod
293     def poll(cls, context):
294         tex = context.texture
295         engine = context.scene.render.engine
296         return tex and ((tex.type == cls.tex_type and not tex.use_nodes) and (engine in cls.COMPAT_ENGINES))
297
298
299 class TEXTURE_PT_clouds(TextureTypePanel, Panel):
300     bl_label = "Clouds"
301     tex_type = 'CLOUDS'
302     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
303
304     def draw(self, context):
305         layout = self.layout
306
307         tex = context.texture
308
309         layout.prop(tex, "cloud_type", expand=True)
310         layout.label(text="Noise:")
311         layout.prop(tex, "noise_type", text="Type", expand=True)
312         layout.prop(tex, "noise_basis", text="Basis")
313
314         split = layout.split()
315
316         col = split.column()
317         col.prop(tex, "noise_scale", text="Size")
318         col.prop(tex, "noise_depth", text="Depth")
319
320         split.prop(tex, "nabla", text="Nabla")
321
322
323 class TEXTURE_PT_wood(TextureTypePanel, Panel):
324     bl_label = "Wood"
325     tex_type = 'WOOD'
326     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
327
328     def draw(self, context):
329         layout = self.layout
330
331         tex = context.texture
332
333         layout.prop(tex, "noise_basis_2", expand=True)
334         layout.prop(tex, "wood_type", expand=True)
335
336         col = layout.column()
337         col.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'}
338         col.label(text="Noise:")
339         col.row().prop(tex, "noise_type", text="Type", expand=True)
340         layout.prop(tex, "noise_basis", text="Basis")
341
342         split = layout.split()
343         split.active = tex.wood_type in {'RINGNOISE', 'BANDNOISE'}
344
345         col = split.column()
346         col.prop(tex, "noise_scale", text="Size")
347         col.prop(tex, "turbulence")
348
349         split.prop(tex, "nabla")
350
351
352 class TEXTURE_PT_marble(TextureTypePanel, Panel):
353     bl_label = "Marble"
354     tex_type = 'MARBLE'
355     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
356
357     def draw(self, context):
358         layout = self.layout
359
360         tex = context.texture
361
362         layout.prop(tex, "marble_type", expand=True)
363         layout.prop(tex, "noise_basis_2", expand=True)
364         layout.label(text="Noise:")
365         layout.prop(tex, "noise_type", text="Type", expand=True)
366         layout.prop(tex, "noise_basis", text="Basis")
367
368         split = layout.split()
369
370         col = split.column()
371         col.prop(tex, "noise_scale", text="Size")
372         col.prop(tex, "noise_depth", text="Depth")
373
374         col = split.column()
375         col.prop(tex, "turbulence")
376         col.prop(tex, "nabla")
377
378
379 class TEXTURE_PT_magic(TextureTypePanel, Panel):
380     bl_label = "Magic"
381     tex_type = 'MAGIC'
382     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
383
384     def draw(self, context):
385         layout = self.layout
386
387         tex = context.texture
388
389         row = layout.row()
390         row.prop(tex, "noise_depth", text="Depth")
391         row.prop(tex, "turbulence")
392
393
394 class TEXTURE_PT_blend(TextureTypePanel, Panel):
395     bl_label = "Blend"
396     tex_type = 'BLEND'
397     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
398
399     def draw(self, context):
400         layout = self.layout
401
402         tex = context.texture
403
404         layout.prop(tex, "progression")
405
406         sub = layout.row()
407
408         sub.active = (tex.progression in {'LINEAR', 'QUADRATIC', 'EASING', 'RADIAL'})
409         sub.prop(tex, "use_flip_axis", expand=True)
410
411
412 class TEXTURE_PT_stucci(TextureTypePanel, Panel):
413     bl_label = "Stucci"
414     tex_type = 'STUCCI'
415     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
416
417     def draw(self, context):
418         layout = self.layout
419
420         tex = context.texture
421
422         layout.prop(tex, "stucci_type", expand=True)
423         layout.label(text="Noise:")
424         layout.prop(tex, "noise_type", text="Type", expand=True)
425         layout.prop(tex, "noise_basis", text="Basis")
426
427         row = layout.row()
428         row.prop(tex, "noise_scale", text="Size")
429         row.prop(tex, "turbulence")
430
431
432 class TEXTURE_PT_image(TextureTypePanel, Panel):
433     bl_label = "Image"
434     tex_type = 'IMAGE'
435     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
436
437     def draw(self, context):
438         layout = self.layout
439
440         tex = context.texture
441
442         layout.template_image(tex, "image", tex.image_user)
443
444
445 def texture_filter_common(tex, layout):
446     layout.label(text="Filter:")
447     layout.prop(tex, "filter_type", text="")
448     if tex.use_mipmap and tex.filter_type in {'AREA', 'EWA', 'FELINE'}:
449         if tex.filter_type == 'FELINE':
450             layout.prop(tex, "filter_probes", text="Probes")
451         else:
452             layout.prop(tex, "filter_eccentricity", text="Eccentricity")
453
454     layout.prop(tex, "filter_size")
455     layout.prop(tex, "use_filter_size_min")
456
457
458 class TEXTURE_PT_image_sampling(TextureTypePanel, Panel):
459     bl_label = "Image Sampling"
460     bl_options = {'DEFAULT_CLOSED'}
461     tex_type = 'IMAGE'
462     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
463
464     def draw(self, context):
465         if context.scene.render.engine == 'BLENDER_GAME':
466             self.draw_bge(context)
467         else:
468             self.draw_bi(context)
469
470     def draw_bi(self, context):
471         layout = self.layout
472
473         idblock = context_tex_datablock(context)
474         tex = context.texture
475         slot = getattr(context, "texture_slot", None)
476
477         split = layout.split()
478
479         col = split.column()
480         col.label(text="Alpha:")
481         row = col.row()
482         row.active = bool(tex.image and tex.image.use_alpha)
483         row.prop(tex, "use_alpha", text="Use")
484         col.prop(tex, "use_calculate_alpha", text="Calculate")
485         col.prop(tex, "invert_alpha", text="Invert")
486         col.separator()
487         col.prop(tex, "use_flip_axis", text="Flip X/Y Axis")
488
489         col = split.column()
490
491         #Only for Material based textures, not for Lamp/World...
492         if slot and isinstance(idblock, Material):
493             col.prop(tex, "use_normal_map")
494             row = col.row()
495             row.active = tex.use_normal_map
496             row.prop(slot, "normal_map_space", text="")
497
498             row = col.row()
499             row.active = not tex.use_normal_map
500             row.prop(tex, "use_derivative_map")
501
502         col.prop(tex, "use_mipmap")
503         row = col.row()
504         row.active = tex.use_mipmap
505         row.prop(tex, "use_mipmap_gauss")
506         col.prop(tex, "use_interpolation")
507
508         texture_filter_common(tex, col)
509
510     def draw_bge(self, context):
511         layout = self.layout
512
513         idblock = context_tex_datablock(context)
514         tex = context.texture
515         slot = getattr(context, "texture_slot", None)
516
517         split = layout.split()
518
519         col = split.column()
520         col.label(text="Alpha:")
521         col.prop(tex, "use_calculate_alpha", text="Calculate")
522         col.prop(tex, "invert_alpha", text="Invert")
523
524         col = split.column()
525
526         #Only for Material based textures, not for Lamp/World...
527         if slot and isinstance(idblock, Material):
528             col.prop(tex, "use_normal_map")
529             row = col.row()
530             row.active = tex.use_normal_map
531             row.prop(slot, "normal_map_space", text="")
532
533             row = col.row()
534             row.active = not tex.use_normal_map
535             row.prop(tex, "use_derivative_map")
536
537
538 class TEXTURE_PT_image_mapping(TextureTypePanel, Panel):
539     bl_label = "Image Mapping"
540     bl_options = {'DEFAULT_CLOSED'}
541     tex_type = 'IMAGE'
542     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
543
544     def draw(self, context):
545         layout = self.layout
546
547         tex = context.texture
548
549         layout.prop(tex, "extension")
550
551         split = layout.split()
552
553         if tex.extension == 'REPEAT':
554             col = split.column(align=True)
555             col.label(text="Repeat:")
556             col.prop(tex, "repeat_x", text="X")
557             col.prop(tex, "repeat_y", text="Y")
558
559             col = split.column(align=True)
560             col.label(text="Mirror:")
561             row = col.row(align=True)
562             row.prop(tex, "use_mirror_x", text="X")
563             row.active = (tex.repeat_x > 1)
564             row = col.row(align=True)
565             row.prop(tex, "use_mirror_y", text="Y")
566             row.active = (tex.repeat_y > 1)
567             layout.separator()
568
569         elif tex.extension == 'CHECKER':
570             col = split.column(align=True)
571             row = col.row(align=True)
572             row.prop(tex, "use_checker_even", text="Even")
573             row.prop(tex, "use_checker_odd", text="Odd")
574
575             col = split.column()
576             col.prop(tex, "checker_distance", text="Distance")
577
578             layout.separator()
579
580         split = layout.split()
581
582         col = split.column(align=True)
583         #col.prop(tex, "crop_rectangle")
584         col.label(text="Crop Minimum:")
585         col.prop(tex, "crop_min_x", text="X")
586         col.prop(tex, "crop_min_y", text="Y")
587
588         col = split.column(align=True)
589         col.label(text="Crop Maximum:")
590         col.prop(tex, "crop_max_x", text="X")
591         col.prop(tex, "crop_max_y", text="Y")
592
593
594 class TEXTURE_PT_envmap(TextureTypePanel, Panel):
595     bl_label = "Environment Map"
596     tex_type = 'ENVIRONMENT_MAP'
597     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
598
599     def draw(self, context):
600         layout = self.layout
601
602         tex = context.texture
603         env = tex.environment_map
604
605         row = layout.row()
606         row.prop(env, "source", expand=True)
607         row.menu("TEXTURE_MT_envmap_specials", icon='DOWNARROW_HLT', text="")
608
609         if env.source == 'IMAGE_FILE':
610             layout.template_ID(tex, "image", open="image.open")
611             layout.template_image(tex, "image", tex.image_user, compact=True)
612         else:
613             layout.prop(env, "mapping")
614             if env.mapping == 'PLANE':
615                 layout.prop(env, "zoom")
616             layout.prop(env, "viewpoint_object")
617
618             split = layout.split()
619
620             col = split.column()
621             col.prop(env, "layers_ignore")
622             col.prop(env, "resolution")
623             col.prop(env, "depth")
624
625             col = split.column(align=True)
626
627             col.label(text="Clipping:")
628             col.prop(env, "clip_start", text="Start")
629             col.prop(env, "clip_end", text="End")
630
631
632 class TEXTURE_PT_envmap_sampling(TextureTypePanel, Panel):
633     bl_label = "Environment Map Sampling"
634     bl_options = {'DEFAULT_CLOSED'}
635     tex_type = 'ENVIRONMENT_MAP'
636     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
637
638     def draw(self, context):
639         layout = self.layout
640
641         tex = context.texture
642
643         texture_filter_common(tex, layout)
644
645
646 class TEXTURE_PT_musgrave(TextureTypePanel, Panel):
647     bl_label = "Musgrave"
648     tex_type = 'MUSGRAVE'
649     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
650
651     def draw(self, context):
652         layout = self.layout
653
654         tex = context.texture
655
656         layout.prop(tex, "musgrave_type")
657
658         split = layout.split()
659
660         col = split.column()
661         col.prop(tex, "dimension_max", text="Dimension")
662         col.prop(tex, "lacunarity")
663         col.prop(tex, "octaves")
664
665         musgrave_type = tex.musgrave_type
666         col = split.column()
667         if musgrave_type in {'HETERO_TERRAIN', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
668             col.prop(tex, "offset")
669         if musgrave_type in {'MULTIFRACTAL', 'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
670             col.prop(tex, "noise_intensity", text="Intensity")
671         if musgrave_type in {'RIDGED_MULTIFRACTAL', 'HYBRID_MULTIFRACTAL'}:
672             col.prop(tex, "gain")
673
674         layout.label(text="Noise:")
675
676         layout.prop(tex, "noise_basis", text="Basis")
677
678         row = layout.row()
679         row.prop(tex, "noise_scale", text="Size")
680         row.prop(tex, "nabla")
681
682
683 class TEXTURE_PT_voronoi(TextureTypePanel, Panel):
684     bl_label = "Voronoi"
685     tex_type = 'VORONOI'
686     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
687
688     def draw(self, context):
689         layout = self.layout
690
691         tex = context.texture
692
693         split = layout.split()
694
695         col = split.column()
696         col.label(text="Distance Metric:")
697         col.prop(tex, "distance_metric", text="")
698         sub = col.column()
699         sub.active = tex.distance_metric == 'MINKOVSKY'
700         sub.prop(tex, "minkovsky_exponent", text="Exponent")
701         col.label(text="Coloring:")
702         col.prop(tex, "color_mode", text="")
703         col.prop(tex, "noise_intensity", text="Intensity")
704
705         col = split.column()
706         sub = col.column(align=True)
707         sub.label(text="Feature Weights:")
708         sub.prop(tex, "weight_1", text="1", slider=True)
709         sub.prop(tex, "weight_2", text="2", slider=True)
710         sub.prop(tex, "weight_3", text="3", slider=True)
711         sub.prop(tex, "weight_4", text="4", slider=True)
712
713         layout.label(text="Noise:")
714         row = layout.row()
715         row.prop(tex, "noise_scale", text="Size")
716         row.prop(tex, "nabla")
717
718
719 class TEXTURE_PT_distortednoise(TextureTypePanel, Panel):
720     bl_label = "Distorted Noise"
721     tex_type = 'DISTORTED_NOISE'
722     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
723
724     def draw(self, context):
725         layout = self.layout
726
727         tex = context.texture
728
729         layout.prop(tex, "noise_distortion")
730         layout.prop(tex, "noise_basis", text="Basis")
731
732         split = layout.split()
733
734         col = split.column()
735         col.prop(tex, "distortion", text="Distortion")
736         col.prop(tex, "noise_scale", text="Size")
737
738         split.prop(tex, "nabla")
739
740
741 class TEXTURE_PT_voxeldata(TextureButtonsPanel, Panel):
742     bl_label = "Voxel Data"
743     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
744
745     @classmethod
746     def poll(cls, context):
747         tex = context.texture
748         engine = context.scene.render.engine
749         return tex and (tex.type == 'VOXEL_DATA' and (engine in cls.COMPAT_ENGINES))
750
751     def draw(self, context):
752         layout = self.layout
753
754         tex = context.texture
755         vd = tex.voxel_data
756
757         layout.prop(vd, "file_format")
758         if vd.file_format in {'BLENDER_VOXEL', 'RAW_8BIT'}:
759             layout.prop(vd, "filepath")
760         if vd.file_format == 'RAW_8BIT':
761             layout.prop(vd, "resolution")
762         elif vd.file_format == 'SMOKE':
763             layout.prop(vd, "domain_object")
764             layout.prop(vd, "smoke_data_type")
765         elif vd.file_format == 'IMAGE_SEQUENCE':
766             layout.template_ID(tex, "image", open="image.open")
767             layout.template_image(tex, "image", tex.image_user, compact=True)
768             #layout.prop(vd, "frame_duration")
769
770         if vd.file_format in {'BLENDER_VOXEL', 'RAW_8BIT'}:
771             layout.prop(vd, "use_still_frame")
772             row = layout.row()
773             row.active = vd.use_still_frame
774             row.prop(vd, "still_frame")
775
776         layout.prop(vd, "interpolation")
777         layout.prop(vd, "extension")
778         layout.prop(vd, "intensity")
779
780
781 class TEXTURE_PT_pointdensity(TextureButtonsPanel, Panel):
782     bl_label = "Point Density"
783     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
784
785     @classmethod
786     def poll(cls, context):
787         tex = context.texture
788         engine = context.scene.render.engine
789         return tex and (tex.type == 'POINT_DENSITY' and (engine in cls.COMPAT_ENGINES))
790
791     def draw(self, context):
792         layout = self.layout
793
794         tex = context.texture
795         pd = tex.point_density
796
797         layout.prop(pd, "point_source", expand=True)
798
799         split = layout.split()
800
801         col = split.column()
802         if pd.point_source == 'PARTICLE_SYSTEM':
803             col.label(text="Object:")
804             col.prop(pd, "object", text="")
805
806             sub = col.column()
807             sub.enabled = bool(pd.object)
808             if pd.object:
809                 sub.label(text="System:")
810                 sub.prop_search(pd, "particle_system", pd.object, "particle_systems", text="")
811             sub.label(text="Cache:")
812             sub.prop(pd, "particle_cache_space", text="")
813         else:
814             col.label(text="Object:")
815             col.prop(pd, "object", text="")
816             col.label(text="Cache:")
817             col.prop(pd, "vertex_cache_space", text="")
818
819         col.separator()
820
821         if pd.point_source == 'PARTICLE_SYSTEM':
822             col.label(text="Color Source:")
823             col.prop(pd, "color_source", text="")
824             if pd.color_source in {'PARTICLE_SPEED', 'PARTICLE_VELOCITY'}:
825                 col.prop(pd, "speed_scale")
826             if pd.color_source in {'PARTICLE_SPEED', 'PARTICLE_AGE'}:
827                 layout.template_color_ramp(pd, "color_ramp", expand=True)
828
829         col = split.column()
830         col.label()
831         col.prop(pd, "radius")
832         col.label(text="Falloff:")
833         col.prop(pd, "falloff", text="")
834         if pd.falloff == 'SOFT':
835             col.prop(pd, "falloff_soft")
836         if pd.falloff == 'PARTICLE_VELOCITY':
837             col.prop(pd, "falloff_speed_scale")
838
839         col.prop(pd, "use_falloff_curve")
840
841         if pd.use_falloff_curve:
842             col = layout.column()
843             col.label(text="Falloff Curve")
844             col.template_curve_mapping(pd, "falloff_curve", brush=False)
845
846
847 class TEXTURE_PT_pointdensity_turbulence(TextureButtonsPanel, Panel):
848     bl_label = "Turbulence"
849     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
850
851     @classmethod
852     def poll(cls, context):
853         tex = context.texture
854         engine = context.scene.render.engine
855         return tex and (tex.type == 'POINT_DENSITY' and (engine in cls.COMPAT_ENGINES))
856
857     def draw_header(self, context):
858         pd = context.texture.point_density
859
860         self.layout.prop(pd, "use_turbulence", text="")
861
862     def draw(self, context):
863         layout = self.layout
864
865         tex = context.texture
866         pd = tex.point_density
867         layout.active = pd.use_turbulence
868
869         split = layout.split()
870
871         col = split.column()
872         col.label(text="Influence:")
873         col.prop(pd, "turbulence_influence", text="")
874         col.label(text="Noise Basis:")
875         col.prop(pd, "noise_basis", text="")
876
877         col = split.column()
878         col.label()
879         col.prop(pd, "turbulence_scale")
880         col.prop(pd, "turbulence_depth")
881         col.prop(pd, "turbulence_strength")
882
883
884 class TEXTURE_PT_ocean(TextureTypePanel, Panel):
885     bl_label = "Ocean"
886     tex_type = 'OCEAN'
887     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
888
889     def draw(self, context):
890         layout = self.layout
891
892         tex = context.texture
893         ot = tex.ocean
894
895         col = layout.column()
896         col.prop(ot, "ocean_object")
897         col.prop(ot, "output")
898
899
900 class TEXTURE_PT_mapping(TextureSlotPanel, Panel):
901     bl_label = "Mapping"
902     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
903
904     @classmethod
905     def poll(cls, context):
906         idblock = context_tex_datablock(context)
907         if isinstance(idblock, Brush) and not context.sculpt_object:
908             return False
909
910         if not getattr(context, "texture_slot", None):
911             return False
912
913         engine = context.scene.render.engine
914         return (engine in cls.COMPAT_ENGINES)
915
916     def draw(self, context):
917         layout = self.layout
918
919         idblock = context_tex_datablock(context)
920
921         tex = context.texture_slot
922
923         if not isinstance(idblock, Brush):
924             split = layout.split(percentage=0.3)
925             col = split.column()
926             col.label(text="Coordinates:")
927             col = split.column()
928             col.prop(tex, "texture_coords", text="")
929
930             if tex.texture_coords == 'ORCO':
931                 """
932                 ob = context.object
933                 if ob and ob.type == 'MESH':
934                     split = layout.split(percentage=0.3)
935                     split.label(text="Mesh:")
936                     split.prop(ob.data, "texco_mesh", text="")
937                 """
938             elif tex.texture_coords == 'UV':
939                 split = layout.split(percentage=0.3)
940                 split.label(text="Map:")
941                 ob = context.object
942                 if ob and ob.type == 'MESH':
943                     split.prop_search(tex, "uv_layer", ob.data, "uv_textures", text="")
944                 else:
945                     split.prop(tex, "uv_layer", text="")
946
947             elif tex.texture_coords == 'OBJECT':
948                 split = layout.split(percentage=0.3)
949                 split.label(text="Object:")
950                 split.prop(tex, "object", text="")
951
952         if isinstance(idblock, Brush):
953             if context.sculpt_object or context.image_paint_object:
954                 brush_texture_settings(layout, idblock, context.sculpt_object)
955         else:
956             if isinstance(idblock, Material):
957                 split = layout.split(percentage=0.3)
958                 split.label(text="Projection:")
959                 split.prop(tex, "mapping", text="")
960
961                 split = layout.split()
962
963                 col = split.column()
964                 if tex.texture_coords in {'ORCO', 'UV'}:
965                     col.prop(tex, "use_from_dupli")
966                     if (idblock.type == 'VOLUME' and tex.texture_coords == 'ORCO'):
967                         col.prop(tex, "use_map_to_bounds")
968                 elif tex.texture_coords == 'OBJECT':
969                     col.prop(tex, "use_from_original")
970                     if (idblock.type == 'VOLUME'):
971                         col.prop(tex, "use_map_to_bounds")
972                 else:
973                     col.label()
974
975                 col = split.column()
976                 row = col.row()
977                 row.prop(tex, "mapping_x", text="")
978                 row.prop(tex, "mapping_y", text="")
979                 row.prop(tex, "mapping_z", text="")
980
981             row = layout.row()
982             row.column().prop(tex, "offset")
983             row.column().prop(tex, "scale")
984
985
986 class TEXTURE_PT_influence(TextureSlotPanel, Panel):
987     bl_label = "Influence"
988     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
989
990     @classmethod
991     def poll(cls, context):
992         idblock = context_tex_datablock(context)
993         if isinstance(idblock, Brush):
994             return False
995
996         if not getattr(context, "texture_slot", None):
997             return False
998
999         engine = context.scene.render.engine
1000         return (engine in cls.COMPAT_ENGINES)
1001
1002     def draw(self, context):
1003
1004         layout = self.layout
1005
1006         idblock = context_tex_datablock(context)
1007
1008         tex = context.texture_slot
1009
1010         def factor_but(layout, toggle, factor, name):
1011             row = layout.row(align=True)
1012             row.prop(tex, toggle, text="")
1013             sub = row.row(align=True)
1014             sub.active = getattr(tex, toggle)
1015             sub.prop(tex, factor, text=name, slider=True)
1016             return sub  # XXX, temp. use_map_normal needs to override.
1017
1018         if isinstance(idblock, Material):
1019             if idblock.type in {'SURFACE', 'WIRE'}:
1020                 split = layout.split()
1021
1022                 col = split.column()
1023                 col.label(text="Diffuse:")
1024                 factor_but(col, "use_map_diffuse", "diffuse_factor", "Intensity")
1025                 factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color")
1026                 factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
1027                 factor_but(col, "use_map_translucency", "translucency_factor", "Translucency")
1028
1029                 col.label(text="Specular:")
1030                 factor_but(col, "use_map_specular", "specular_factor", "Intensity")
1031                 factor_but(col, "use_map_color_spec", "specular_color_factor", "Color")
1032                 factor_but(col, "use_map_hardness", "hardness_factor", "Hardness")
1033
1034                 col = split.column()
1035                 col.label(text="Shading:")
1036                 factor_but(col, "use_map_ambient", "ambient_factor", "Ambient")
1037                 factor_but(col, "use_map_emit", "emit_factor", "Emit")
1038                 factor_but(col, "use_map_mirror", "mirror_factor", "Mirror")
1039                 factor_but(col, "use_map_raymir", "raymir_factor", "Ray Mirror")
1040
1041                 col.label(text="Geometry:")
1042                 # XXX replace 'or' when displacement is fixed to not rely on normal influence value.
1043                 sub_tmp = factor_but(col, "use_map_normal", "normal_factor", "Normal")
1044                 sub_tmp.active = (tex.use_map_normal or tex.use_map_displacement)
1045                 # END XXX
1046
1047                 factor_but(col, "use_map_warp", "warp_factor", "Warp")
1048                 factor_but(col, "use_map_displacement", "displacement_factor", "Displace")
1049
1050                 #~ sub = col.column()
1051                 #~ sub.active = tex.use_map_translucency or tex.map_emit or tex.map_alpha or tex.map_raymir or tex.map_hardness or tex.map_ambient or tex.map_specularity or tex.map_reflection or tex.map_mirror
1052                 #~ sub.prop(tex, "default_value", text="Amount", slider=True)
1053             elif idblock.type == 'HALO':
1054                 layout.label(text="Halo:")
1055
1056                 split = layout.split()
1057
1058                 col = split.column()
1059                 factor_but(col, "use_map_color_diffuse", "diffuse_color_factor", "Color")
1060                 factor_but(col, "use_map_alpha", "alpha_factor", "Alpha")
1061
1062                 col = split.column()
1063                 factor_but(col, "use_map_raymir", "raymir_factor", "Size")
1064                 factor_but(col, "use_map_hardness", "hardness_factor", "Hardness")
1065                 factor_but(col, "use_map_translucency", "translucency_factor", "Add")
1066             elif idblock.type == 'VOLUME':
1067                 split = layout.split()
1068
1069                 col = split.column()
1070                 factor_but(col, "use_map_density", "density_factor", "Density")
1071                 factor_but(col, "use_map_emission", "emission_factor", "Emission")
1072                 factor_but(col, "use_map_scatter", "scattering_factor", "Scattering")
1073                 factor_but(col, "use_map_reflect", "reflection_factor", "Reflection")
1074
1075                 col = split.column()
1076                 col.label(text=" ")
1077                 factor_but(col, "use_map_color_emission", "emission_color_factor", "Emission Color")
1078                 factor_but(col, "use_map_color_transmission", "transmission_color_factor", "Transmission Color")
1079                 factor_but(col, "use_map_color_reflection", "reflection_color_factor", "Reflection Color")
1080
1081         elif isinstance(idblock, Lamp):
1082             split = layout.split()
1083
1084             col = split.column()
1085             factor_but(col, "use_map_color", "color_factor", "Color")
1086
1087             col = split.column()
1088             factor_but(col, "use_map_shadow", "shadow_factor", "Shadow")
1089
1090         elif isinstance(idblock, World):
1091             split = layout.split()
1092
1093             col = split.column()
1094             factor_but(col, "use_map_blend", "blend_factor", "Blend")
1095             factor_but(col, "use_map_horizon", "horizon_factor", "Horizon")
1096
1097             col = split.column()
1098             factor_but(col, "use_map_zenith_up", "zenith_up_factor", "Zenith Up")
1099             factor_but(col, "use_map_zenith_down", "zenith_down_factor", "Zenith Down")
1100         elif isinstance(idblock, ParticleSettings):
1101             split = layout.split()
1102
1103             col = split.column()
1104             col.label(text="General:")
1105             factor_but(col, "use_map_time", "time_factor", "Time")
1106             factor_but(col, "use_map_life", "life_factor", "Lifetime")
1107             factor_but(col, "use_map_density", "density_factor", "Density")
1108             factor_but(col, "use_map_size", "size_factor", "Size")
1109
1110             col = split.column()
1111             col.label(text="Physics:")
1112             factor_but(col, "use_map_velocity", "velocity_factor", "Velocity")
1113             factor_but(col, "use_map_damp", "damp_factor", "Damp")
1114             factor_but(col, "use_map_gravity", "gravity_factor", "Gravity")
1115             factor_but(col, "use_map_field", "field_factor", "Force Fields")
1116
1117             layout.label(text="Hair:")
1118
1119             split = layout.split()
1120
1121             col = split.column()
1122             factor_but(col, "use_map_length", "length_factor", "Length")
1123             factor_but(col, "use_map_clump", "clump_factor", "Clump")
1124
1125             col = split.column()
1126             factor_but(col, "use_map_kink", "kink_factor", "Kink")
1127             factor_but(col, "use_map_rough", "rough_factor", "Rough")
1128
1129         layout.separator()
1130
1131         if not isinstance(idblock, ParticleSettings):
1132             split = layout.split()
1133
1134             col = split.column()
1135             col.prop(tex, "blend_type", text="Blend")
1136             col.prop(tex, "use_rgb_to_intensity")
1137             # color is used on gray-scale textures even when use_rgb_to_intensity is disabled.
1138             col.prop(tex, "color", text="")
1139
1140             col = split.column()
1141             col.prop(tex, "invert", text="Negative")
1142             col.prop(tex, "use_stencil")
1143
1144         if isinstance(idblock, Material) or isinstance(idblock, World):
1145             col.prop(tex, "default_value", text="DVar", slider=True)
1146
1147         if isinstance(idblock, Material):
1148             layout.label(text="Bump Mapping:")
1149
1150             # only show bump settings if activated but not for normal-map images
1151             row = layout.row()
1152
1153             sub = row.row()
1154             sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and (tex.texture.use_normal_map or tex.texture.use_derivative_map))
1155             sub.prop(tex, "bump_method", text="Method")
1156
1157             # the space setting is supported for: derivative-maps + bump-maps (DEFAULT,BEST_QUALITY), not for normal-maps
1158             sub = row.row()
1159             sub.active = (tex.use_map_normal or tex.use_map_warp) and not (tex.texture.type == 'IMAGE' and tex.texture.use_normal_map) and ((tex.bump_method in {'BUMP_LOW_QUALITY', 'BUMP_MEDIUM_QUALITY', 'BUMP_BEST_QUALITY'}) or (tex.texture.type == 'IMAGE' and tex.texture.use_derivative_map))
1160             sub.prop(tex, "bump_objectspace", text="Space")
1161
1162
1163 class TEXTURE_PT_custom_props(TextureButtonsPanel, PropertyPanel, Panel):
1164     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
1165     _context_path = "texture"
1166     _property_type = Texture
1167
1168 if __name__ == "__main__":  # only for live edit.
1169     bpy.utils.register_module(__name__)