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