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