Related to #29092: make the working of the Mist Intensity option more clear in
[blender.git] / release / scripts / startup / bl_ui / properties_world.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 Panel
22 from rna_prop_ui import PropertyPanel
23
24
25 class WorldButtonsPanel():
26     bl_space_type = 'PROPERTIES'
27     bl_region_type = 'WINDOW'
28     bl_context = "world"
29     # COMPAT_ENGINES must be defined in each subclass, external engines can add themselves here
30
31     @classmethod
32     def poll(cls, context):
33         return (context.world and context.scene.render.engine in cls.COMPAT_ENGINES)
34
35
36 class WORLD_PT_context_world(WorldButtonsPanel, Panel):
37     bl_label = ""
38     bl_options = {'HIDE_HEADER'}
39     COMPAT_ENGINES = {'BLENDER_RENDER'}
40
41     @classmethod
42     def poll(cls, context):
43         rd = context.scene.render
44         return (not rd.use_game_engine) and (rd.engine in cls.COMPAT_ENGINES)
45
46     def draw(self, context):
47         layout = self.layout
48
49         scene = context.scene
50         world = context.world
51         space = context.space_data
52
53         texture_count = world and len(world.texture_slots.keys())
54
55         split = layout.split(percentage=0.65)
56         if scene:
57             split.template_ID(scene, "world", new="world.new")
58         elif world:
59             split.template_ID(space, "pin_id")
60
61         if texture_count:
62             split.label(text=str(texture_count), icon='TEXTURE')
63
64
65 class WORLD_PT_preview(WorldButtonsPanel, Panel):
66     bl_label = "Preview"
67     COMPAT_ENGINES = {'BLENDER_RENDER'}
68
69     @classmethod
70     def poll(cls, context):
71         rd = context.scene.render
72         return (context.world) and (not rd.use_game_engine) and (rd.engine in cls.COMPAT_ENGINES)
73
74     def draw(self, context):
75         self.layout.template_preview(context.world)
76
77
78 class WORLD_PT_world(WorldButtonsPanel, Panel):
79     bl_label = "World"
80     COMPAT_ENGINES = {'BLENDER_RENDER'}
81
82     def draw(self, context):
83         layout = self.layout
84         world = context.world
85
86         row = layout.row()
87         row.prop(world, "use_sky_paper")
88         row.prop(world, "use_sky_blend")
89         row.prop(world, "use_sky_real")
90
91         row = layout.row()
92         row.column().prop(world, "horizon_color")
93         col = row.column()
94         col.prop(world, "zenith_color")
95         col.active = world.use_sky_blend
96         row.column().prop(world, "ambient_color")
97
98         row = layout.row()
99         row.prop(world, "exposure")
100         row.prop(world, "color_range")
101
102
103 class WORLD_PT_ambient_occlusion(WorldButtonsPanel, Panel):
104     bl_label = "Ambient Occlusion"
105     COMPAT_ENGINES = {'BLENDER_RENDER'}
106
107     def draw_header(self, context):
108         light = context.world.light_settings
109         self.layout.prop(light, "use_ambient_occlusion", text="")
110
111     def draw(self, context):
112         layout = self.layout
113         light = context.world.light_settings
114
115         layout.active = light.use_ambient_occlusion
116
117         split = layout.split()
118         split.prop(light, "ao_factor", text="Factor")
119         split.prop(light, "ao_blend_type", text="")
120
121
122 class WORLD_PT_environment_lighting(WorldButtonsPanel, Panel):
123     bl_label = "Environment Lighting"
124     COMPAT_ENGINES = {'BLENDER_RENDER'}
125
126     def draw_header(self, context):
127         light = context.world.light_settings
128         self.layout.prop(light, "use_environment_light", text="")
129
130     def draw(self, context):
131         layout = self.layout
132         light = context.world.light_settings
133
134         layout.active = light.use_environment_light
135
136         split = layout.split()
137         split.prop(light, "environment_energy", text="Energy")
138         split.prop(light, "environment_color", text="")
139
140
141 class WORLD_PT_indirect_lighting(WorldButtonsPanel, Panel):
142     bl_label = "Indirect Lighting"
143     COMPAT_ENGINES = {'BLENDER_RENDER'}
144
145     def draw_header(self, context):
146         light = context.world.light_settings
147         self.layout.prop(light, "use_indirect_light", text="")
148
149     def draw(self, context):
150         layout = self.layout
151         light = context.world.light_settings
152
153         layout.active = light.use_indirect_light and light.gather_method == 'APPROXIMATE'
154
155         split = layout.split()
156         split.prop(light, "indirect_factor", text="Factor")
157         split.prop(light, "indirect_bounces", text="Bounces")
158
159         if light.gather_method == 'RAYTRACE':
160             layout.label(text="Only works with Approximate gather method")
161
162
163 class WORLD_PT_gather(WorldButtonsPanel, Panel):
164     bl_label = "Gather"
165     COMPAT_ENGINES = {'BLENDER_RENDER'}
166
167     def draw(self, context):
168         layout = self.layout
169         light = context.world.light_settings
170
171         layout.active = light.use_ambient_occlusion or light.use_environment_light or light.use_indirect_light
172
173         layout.prop(light, "gather_method", expand=True)
174
175         split = layout.split()
176
177         col = split.column()
178         col.label(text="Attenuation:")
179         if light.gather_method == 'RAYTRACE':
180             col.prop(light, "distance")
181         col.prop(light, "use_falloff")
182         sub = col.row()
183         sub.active = light.use_falloff
184         sub.prop(light, "falloff_strength", text="Strength")
185
186         if light.gather_method == 'RAYTRACE':
187             col = split.column()
188
189             col.label(text="Sampling:")
190             col.prop(light, "sample_method", text="")
191
192             sub = col.column()
193             sub.prop(light, "samples")
194
195             if light.sample_method == 'ADAPTIVE_QMC':
196                 sub.prop(light, "threshold")
197                 sub.prop(light, "adapt_to_speed", slider=True)
198             elif light.sample_method == 'CONSTANT_JITTERED':
199                 sub.prop(light, "bias")
200
201         if light.gather_method == 'APPROXIMATE':
202             col = split.column()
203
204             col.label(text="Sampling:")
205             col.prop(light, "passes")
206             col.prop(light, "error_threshold", text="Error")
207             col.prop(light, "use_cache")
208             col.prop(light, "correction")
209
210
211 class WORLD_PT_mist(WorldButtonsPanel, Panel):
212     bl_label = "Mist"
213     bl_options = {'DEFAULT_CLOSED'}
214     COMPAT_ENGINES = {'BLENDER_RENDER'}
215
216     def draw_header(self, context):
217         world = context.world
218
219         self.layout.prop(world.mist_settings, "use_mist", text="")
220
221     def draw(self, context):
222         layout = self.layout
223         world = context.world
224
225         layout.active = world.mist_settings.use_mist
226
227         split = layout.split()
228
229         col = split.column()
230         col.prop(world.mist_settings, "intensity")
231         col.prop(world.mist_settings, "start")
232
233         col = split.column()
234         col.prop(world.mist_settings, "depth")
235         col.prop(world.mist_settings, "height")
236
237         layout.prop(world.mist_settings, "falloff")
238
239
240 class WORLD_PT_stars(WorldButtonsPanel, Panel):
241     bl_label = "Stars"
242     bl_options = {'DEFAULT_CLOSED'}
243     COMPAT_ENGINES = {'BLENDER_RENDER'}
244
245     def draw_header(self, context):
246         world = context.world
247
248         self.layout.prop(world.star_settings, "use_stars", text="")
249
250     def draw(self, context):
251         layout = self.layout
252         world = context.world
253
254         layout.active = world.star_settings.use_stars
255
256         split = layout.split()
257
258         col = split.column()
259         col.prop(world.star_settings, "size")
260         col.prop(world.star_settings, "color_random", text="Colors")
261
262         col = split.column()
263         col.prop(world.star_settings, "distance_min", text="Min. Dist")
264         col.prop(world.star_settings, "average_separation", text="Separation")
265
266
267 class WORLD_PT_custom_props(WorldButtonsPanel, PropertyPanel, Panel):
268     COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'}
269     _context_path = "world"
270     _property_type = bpy.types.World
271
272 if __name__ == "__main__":  # only for live edit.
273     bpy.utils.register_module(__name__)