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