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