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