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