poll() as a python '@staticmethod' was too limiting and didnt allow useful base class...
[blender.git] / release / scripts / ui / properties_data_lamp.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 rna_prop_ui import PropertyPanel
22
23
24 class LAMP_MT_sunsky_presets(bpy.types.Menu):
25     bl_label = "Sun & Sky Presets"
26     preset_subdir = "sunsky"
27     preset_operator = "script.execute_preset"
28     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
29     draw = bpy.types.Menu.draw_preset
30
31
32 class DataButtonsPanel():
33     bl_space_type = 'PROPERTIES'
34     bl_region_type = 'WINDOW'
35     bl_context = "data"
36
37     @classmethod
38     def poll(cls, context):
39         engine = context.scene.render.engine
40         return context.lamp and (engine in cls.COMPAT_ENGINES)
41
42
43 class DATA_PT_preview(DataButtonsPanel, bpy.types.Panel):
44     bl_label = "Preview"
45     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
46
47     def draw(self, context):
48         self.layout.template_preview(context.lamp)
49
50 class DATA_PT_context_lamp(DataButtonsPanel, bpy.types.Panel):
51     bl_label = ""
52     bl_show_header = False
53     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
54
55     def draw(self, context):
56         layout = self.layout
57
58         ob = context.object
59         lamp = context.lamp
60         space = context.space_data
61
62         split = layout.split(percentage=0.65)
63
64         if ob:
65             split.template_ID(ob, "data")
66             split.separator()
67         elif lamp:
68             split.template_ID(space, "pin_id")
69             split.separator()
70
71
72 class DATA_PT_custom_props_lamp(DataButtonsPanel, PropertyPanel, bpy.types.Panel):
73     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
74     _context_path = "object.data"
75
76
77 class DATA_PT_lamp(DataButtonsPanel, bpy.types.Panel):
78     bl_label = "Lamp"
79     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
80
81     def draw(self, context):
82         layout = self.layout
83
84         lamp = context.lamp
85
86         layout.prop(lamp, "type", expand=True)
87
88         split = layout.split()
89
90         col = split.column()
91         sub = col.column()
92         sub.prop(lamp, "color", text="")
93         sub.prop(lamp, "energy")
94
95         if lamp.type in ('POINT', 'SPOT'):
96             sub.label(text="Falloff:")
97             sub.prop(lamp, "falloff_type", text="")
98             sub.prop(lamp, "distance")
99
100             if lamp.falloff_type == 'LINEAR_QUADRATIC_WEIGHTED':
101                 col.label(text="Attenuation Factors:")
102                 sub = col.column(align=True)
103                 sub.prop(lamp, "linear_attenuation", slider=True, text="Linear")
104                 sub.prop(lamp, "quadratic_attenuation", slider=True, text="Quadratic")
105
106             col.prop(lamp, "sphere")
107
108         if lamp.type == 'AREA':
109             col.prop(lamp, "distance")
110             col.prop(lamp, "gamma")
111
112         col = split.column()
113         col.prop(lamp, "negative")
114         col.prop(lamp, "layer", text="This Layer Only")
115         col.prop(lamp, "specular")
116         col.prop(lamp, "diffuse")
117
118
119 class DATA_PT_sunsky(DataButtonsPanel, bpy.types.Panel):
120     bl_label = "Sky & Atmosphere"
121     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
122
123     @classmethod
124     def poll(cls, context):
125         lamp = context.lamp
126         engine = context.scene.render.engine
127         return (lamp and lamp.type == 'SUN') and (engine in cls.COMPAT_ENGINES)
128
129     def draw(self, context):
130         layout = self.layout
131
132         lamp = context.lamp.sky
133
134         row = layout.row(align=True)
135         row.prop(lamp, "use_sky")
136         row.menu("LAMP_MT_sunsky_presets", text=bpy.types.LAMP_MT_sunsky_presets.bl_label)
137         row.operator("lamp.sunsky_preset_add", text="", icon="ZOOMIN")
138
139         row = layout.row()
140         row.active = lamp.use_sky or lamp.use_atmosphere
141         row.prop(lamp, "atmosphere_turbidity", text="Turbidity")
142
143         split = layout.split()
144
145         col = split.column()
146         col.active = lamp.use_sky
147         col.label(text="Blending:")
148         sub = col.column()
149         sub.prop(lamp, "sky_blend_type", text="")
150         sub.prop(lamp, "sky_blend", text="Factor")
151
152         col.label(text="Color Space:")
153         sub = col.column()
154         sub.row().prop(lamp, "sky_color_space", expand=True)
155         sub.prop(lamp, "sky_exposure", text="Exposure")
156
157         col = split.column()
158         col.active = lamp.use_sky
159         col.label(text="Horizon:")
160         sub = col.column()
161         sub.prop(lamp, "horizon_brightness", text="Brightness")
162         sub.prop(lamp, "spread", text="Spread")
163
164         col.label(text="Sun:")
165         sub = col.column()
166         sub.prop(lamp, "sun_brightness", text="Brightness")
167         sub.prop(lamp, "sun_size", text="Size")
168         sub.prop(lamp, "backscattered_light", slider=True, text="Back Light")
169
170         layout.separator()
171
172         layout.prop(lamp, "use_atmosphere")
173
174         split = layout.split()
175
176         col = split.column()
177         col.active = lamp.use_atmosphere
178         col.label(text="Intensity:")
179         col.prop(lamp, "sun_intensity", text="Sun")
180         col.prop(lamp, "atmosphere_distance_factor", text="Distance")
181
182         col = split.column()
183         col.active = lamp.use_atmosphere
184         col.label(text="Scattering:")
185         sub = col.column(align=True)
186         sub.prop(lamp, "atmosphere_inscattering", slider=True, text="Inscattering")
187         sub.prop(lamp, "atmosphere_extinction", slider=True, text="Extinction")
188
189
190 class DATA_PT_shadow(DataButtonsPanel, bpy.types.Panel):
191     bl_label = "Shadow"
192     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
193
194     @classmethod
195     def poll(cls, context):
196         lamp = context.lamp
197         engine = context.scene.render.engine
198         return (lamp and lamp.type in ('POINT', 'SUN', 'SPOT', 'AREA')) and (engine in cls.COMPAT_ENGINES)
199
200     def draw(self, context):
201         layout = self.layout
202
203         lamp = context.lamp
204
205         layout.prop(lamp, "shadow_method", expand=True)
206
207         if lamp.shadow_method == 'NOSHADOW' and lamp.type == 'AREA':
208             split = layout.split()
209
210             col= split.column()
211             col.label(text="Form factor sampling:")
212             
213             sub=col.row(align=True)
214
215             if lamp.shape == 'SQUARE':
216                 sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
217             elif lamp.shape == 'RECTANGLE':
218                 sub.prop(lamp, "shadow_ray_samples_x", text="Samples X")
219                 sub.prop(lamp, "shadow_ray_samples_y", text="Samples Y")
220
221         if lamp.shadow_method != 'NOSHADOW':
222             split = layout.split()
223
224             col = split.column()
225             col.prop(lamp, "shadow_color", text="")
226
227             col = split.column()
228             col.prop(lamp, "shadow_layer", text="This Layer Only")
229             col.prop(lamp, "only_shadow")
230
231         if lamp.shadow_method == 'RAY_SHADOW':
232             split = layout.split()
233             
234             col = split.column()
235             col.label(text="Sampling:")
236             
237             if lamp.type in ('POINT', 'SUN', 'SPOT'):
238                 sub = col.row()
239                 
240                 sub.prop(lamp, "shadow_ray_samples", text="Samples")
241                 sub.prop(lamp, "shadow_soft_size", text="Soft Size")
242                 
243             elif lamp.type == 'AREA':
244                 sub = col.row(align=True)
245                 
246                 if lamp.shape == 'SQUARE':
247                     sub.prop(lamp, "shadow_ray_samples_x", text="Samples")
248                 elif lamp.shape == 'RECTANGLE':
249                     sub.prop(lamp, "shadow_ray_samples_x", text="Samples X")
250                     sub.prop(lamp, "shadow_ray_samples_y", text="Samples Y")
251
252             col.row().prop(lamp, "shadow_ray_sampling_method", expand=True)
253
254             split = layout.split()
255             col = split.column()
256             
257             if lamp.shadow_ray_sampling_method == 'ADAPTIVE_QMC':
258                 col.prop(lamp, "shadow_adaptive_threshold", text="Threshold")
259                 col = split.column()
260             
261             if lamp.type == 'AREA' and lamp.shadow_ray_sampling_method == 'CONSTANT_JITTERED':
262                 col = split.column()
263                 col = split.column()
264                 col.prop(lamp, "umbra")
265                 col.prop(lamp, "dither")
266                 col.prop(lamp, "jitter")
267
268         elif lamp.shadow_method == 'BUFFER_SHADOW':
269             col = layout.column()
270             col.label(text="Buffer Type:")
271             col.row().prop(lamp, "shadow_buffer_type", expand=True)
272
273             if lamp.shadow_buffer_type in ('REGULAR', 'HALFWAY', 'DEEP'):
274                 split = layout.split()
275
276                 col = split.column()
277                 col.label(text="Filter Type:")
278                 col.prop(lamp, "shadow_filter_type", text="")
279                 sub = col.column(align=True)
280                 sub.prop(lamp, "shadow_buffer_soft", text="Soft")
281                 sub.prop(lamp, "shadow_buffer_bias", text="Bias")
282
283                 col = split.column()
284                 col.label(text="Sample Buffers:")
285                 col.prop(lamp, "shadow_sample_buffers", text="")
286                 sub = col.column(align=True)
287                 sub.prop(lamp, "shadow_buffer_size", text="Size")
288                 sub.prop(lamp, "shadow_buffer_samples", text="Samples")
289                 if lamp.shadow_buffer_type == 'DEEP':
290                     col.prop(lamp, "compression_threshold")
291
292             elif lamp.shadow_buffer_type == 'IRREGULAR':
293                 layout.prop(lamp, "shadow_buffer_bias", text="Bias")
294
295             split = layout.split()
296
297             col = split.column()
298             col.prop(lamp, "auto_clip_start", text="Autoclip Start")
299             sub = col.column()
300             sub.active = not lamp.auto_clip_start
301             sub.prop(lamp, "shadow_buffer_clip_start", text="Clip Start")
302
303             col = split.column()
304             col.prop(lamp, "auto_clip_end", text="Autoclip End")
305             sub = col.column()
306             sub.active = not lamp.auto_clip_end
307             sub.prop(lamp, "shadow_buffer_clip_end", text=" Clip End")
308
309
310 class DATA_PT_area(DataButtonsPanel, bpy.types.Panel):
311     bl_label = "Area Shape"
312     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
313
314     @classmethod
315     def poll(cls, context):
316         lamp = context.lamp
317         engine = context.scene.render.engine
318         return (lamp and lamp.type == 'AREA') and (engine in cls.COMPAT_ENGINES)
319
320     def draw(self, context):
321         lamp = context.lamp
322
323         layout = self.layout
324         split = layout.split()
325
326         col = split.column()
327         
328         col.row().prop(lamp, "shape", expand=True)
329         sub = col.row(align=True)
330
331         if (lamp.shape == 'SQUARE'):
332             sub.prop(lamp, "size")
333         elif (lamp.shape == 'RECTANGLE'):
334             sub.prop(lamp, "size", text="Size X")
335             sub.prop(lamp, "size_y", text="Size Y")
336
337
338 class DATA_PT_spot(DataButtonsPanel, bpy.types.Panel):
339     bl_label = "Spot Shape"
340     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
341
342     @classmethod
343     def poll(cls, context):
344         lamp = context.lamp
345         engine = context.scene.render.engine
346         return (lamp and lamp.type == 'SPOT') and (engine in cls.COMPAT_ENGINES)
347
348     def draw(self, context):
349         layout = self.layout
350
351         lamp = context.lamp
352
353         split = layout.split()
354
355         col = split.column()
356         sub = col.column()
357         sub.prop(lamp, "spot_size", text="Size")
358         sub.prop(lamp, "spot_blend", text="Blend", slider=True)
359         col.prop(lamp, "square")
360         col.prop(lamp, "show_cone")
361
362         col = split.column()
363
364         col.prop(lamp, "halo")
365         sub = col.column(align=True)
366         sub.active = lamp.halo
367         sub.prop(lamp, "halo_intensity", text="Intensity")
368         if lamp.shadow_method == 'BUFFER_SHADOW':
369             sub.prop(lamp, "halo_step", text="Step")
370
371
372 class DATA_PT_falloff_curve(DataButtonsPanel, bpy.types.Panel):
373     bl_label = "Falloff Curve"
374     bl_default_closed = True
375     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
376
377     @classmethod
378     def poll(cls, context):
379         lamp = context.lamp
380         engine = context.scene.render.engine
381
382         return (lamp and lamp.type in ('POINT', 'SPOT') and lamp.falloff_type == 'CUSTOM_CURVE') and (engine in cls.COMPAT_ENGINES)
383
384     def draw(self, context):
385         lamp = context.lamp
386
387         self.layout.template_curve_mapping(lamp, "falloff_curve")
388
389
390 def register():
391     pass
392
393
394 def unregister():
395     pass
396
397 if __name__ == "__main__":
398     register()