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