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