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