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