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