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