Cleanup: unused vars, imports, pep8
[blender.git] / intern / cycles / blender / addon / version_update.py
1 #
2 # Copyright 2011-2014 Blender Foundation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 #
16
17 # <pep8 compliant>
18
19 import bpy
20
21 from bpy.app.handlers import persistent
22
23
24 def check_is_new_shading_ntree(node_tree):
25     for node in node_tree.nodes:
26         # If material has any node with ONLY new shading system
27         # compatibility then it's considered a Cycles material
28         # and versioning code would need to perform on it.
29         #
30         # We can not check for whether NEW_SHADING in compatibility
31         # because some nodes could have compatibility with both old
32         # and new shading system and they can't be used for any
33         # decision here.
34         if node.shading_compatibility == {'NEW_SHADING'}:
35             return True
36
37         # If node is only compatible with old shading system
38         # then material can not be Cycles material and we
39         # can stopiterating nodes now.
40         if node.shading_compatibility == {'OLD_SHADING'}:
41             return False
42     return False
43
44
45 def check_is_new_shading_material(material):
46     if not material.node_tree:
47         return False
48     return check_is_new_shading_ntree(material.node_tree)
49
50
51 def check_is_new_shading_world(world):
52     if not world.node_tree:
53         return False
54     return check_is_new_shading_ntree(world.node_tree)
55
56
57 def check_is_new_shading_lamp(lamp):
58     if not lamp.node_tree:
59         return False
60     return check_is_new_shading_ntree(lamp.node_tree)
61
62
63 def foreach_notree_node(nodetree, callback, traversed):
64     if nodetree in traversed:
65         return
66     traversed.add(nodetree)
67     for node in nodetree.nodes:
68         callback(node)
69         if node.bl_idname == 'ShaderNodeGroup':
70             foreach_notree_node(node.node_tree, callback, traversed)
71
72
73 def foreach_cycles_node(callback):
74     traversed = set()
75     for material in bpy.data.materials:
76         if check_is_new_shading_material(material):
77                 foreach_notree_node(material.node_tree,
78                                     callback,
79                                     traversed)
80     for world in bpy.data.worlds:
81         if check_is_new_shading_world(world):
82                 foreach_notree_node(world.node_tree,
83                                     callback,
84                                     traversed)
85     for lamp in bpy.data.lamps:
86         if check_is_new_shading_world(lamp):
87                 foreach_notree_node(lamp.node_tree,
88                                     callback,
89                                     traversed)
90
91
92 def mapping_node_order_flip(node):
93     """
94     Flip euler order of mapping shader node
95     """
96     if node.bl_idname == 'ShaderNodeMapping':
97         rot = node.rotation.copy()
98         rot.order = 'ZYX'
99         quat = rot.to_quaternion()
100         node.rotation = quat.to_euler('XYZ')
101
102
103 def vector_curve_node_remap(node):
104     """
105     Remap values of vector curve node from normalized to absolute values
106     """
107     if node.bl_idname == 'ShaderNodeVectorCurve':
108         node.mapping.use_clip = False
109         for curve in node.mapping.curves:
110             for point in curve.points:
111                 point.location.x = (point.location.x * 2.0) - 1.0
112                 point.location.y = (point.location.y - 0.5) * 2.0
113         node.mapping.update()
114
115
116 def custom_bake_remap(scene):
117     """
118     Remap bake types into the new types and set the flags accordingly
119     """
120     bake_lookup = (
121         'COMBINED',
122         'AO',
123         'SHADOW',
124         'NORMAL',
125         'UV',
126         'EMIT',
127         'ENVIRONMENT',
128         'DIFFUSE_DIRECT',
129         'DIFFUSE_INDIRECT',
130         'DIFFUSE_COLOR',
131         'GLOSSY_DIRECT',
132         'GLOSSY_INDIRECT',
133         'GLOSSY_COLOR',
134         'TRANSMISSION_DIRECT',
135         'TRANSMISSION_INDIRECT',
136         'TRANSMISSION_COLOR',
137         'SUBSURFACE_DIRECT',
138         'SUBSURFACE_INDIRECT',
139         'SUBSURFACE_COLOR')
140
141     diffuse_direct_idx = bake_lookup.index('DIFFUSE_DIRECT')
142
143     cscene = scene.cycles
144
145     # Old bake type
146     bake_type_idx = cscene.get("bake_type")
147
148     if bake_type_idx is None:
149         cscene.bake_type = 'COMBINED'
150         return
151
152     # File doesn't need versioning
153     if bake_type_idx < diffuse_direct_idx:
154         return
155
156     # File needs versioning
157     bake_type = bake_lookup[bake_type_idx]
158     cscene.bake_type, end = bake_type.split('_')
159
160     if end == 'DIRECT':
161         scene.render.bake.use_pass_indirect = False
162         scene.render.bake.use_pass_color = False
163
164     elif end == 'INDIRECT':
165         scene.render.bake.use_pass_direct = False
166         scene.render.bake.use_pass_color = False
167
168     elif end == 'COLOR':
169         scene.render.bake.use_pass_direct = False
170         scene.render.bake.use_pass_indirect = False
171
172
173 @persistent
174 def do_versions(self):
175     # We don't modify startup file because it assumes to
176     # have all the default values only.
177     if not bpy.data.is_saved:
178         return
179
180     # Clamp Direct/Indirect separation in 270
181     if bpy.data.version <= (2, 70, 0):
182         for scene in bpy.data.scenes:
183             cscene = scene.cycles
184             sample_clamp = cscene.get("sample_clamp", False)
185             if (sample_clamp and
186                 not cscene.is_property_set("sample_clamp_direct") and
187                 not cscene.is_property_set("sample_clamp_indirect")):
188
189                 cscene.sample_clamp_direct = sample_clamp
190                 cscene.sample_clamp_indirect = sample_clamp
191
192     # Change of Volume Bounces in 271
193     if bpy.data.version <= (2, 71, 0):
194         for scene in bpy.data.scenes:
195             cscene = scene.cycles
196             if not cscene.is_property_set("volume_bounces"):
197                 cscene.volume_bounces = 1
198
199     # Caustics Reflective/Refractive separation in 272
200     if bpy.data.version <= (2, 72, 0):
201         for scene in bpy.data.scenes:
202             cscene = scene.cycles
203             if (cscene.get("no_caustics", False) and
204                 not cscene.is_property_set("caustics_reflective") and
205                 not cscene.is_property_set("caustics_refractive")):
206
207                 cscene.caustics_reflective = False
208                 cscene.caustics_refractive = False
209
210     # Euler order was ZYX in previous versions.
211     if bpy.data.version <= (2, 73, 4):
212         foreach_cycles_node(mapping_node_order_flip)
213
214     if bpy.data.version <= (2, 76, 5):
215         foreach_cycles_node(vector_curve_node_remap)
216
217     # Baking types changed
218     if bpy.data.version <= (2, 76, 6):
219         for scene in bpy.data.scenes:
220             custom_bake_remap(scene)
221
222     # Several default changes for 2.77
223     if bpy.data.version <= (2, 76, 8):
224         for scene in bpy.data.scenes:
225             cscene = scene.cycles
226
227             # Samples
228             if not cscene.is_property_set("samples"):
229                 cscene.samples = 10
230
231             # Preview Samples
232             if not cscene.is_property_set("preview_samples"):
233                 cscene.preview_samples = 10
234
235             # Filter
236             if not cscene.is_property_set("filter_type"):
237                 cscene.pixel_filter_type = 'GAUSSIAN'
238
239             # Tile Order
240             if not cscene.is_property_set("tile_order"):
241                 cscene.tile_order = 'CENTER'
242
243         for lamp in bpy.data.lamps:
244             clamp = lamp.cycles
245
246             # MIS
247             if not clamp.is_property_set("use_multiple_importance_sampling"):
248                 clamp.use_multiple_importance_sampling = False
249
250         for mat in bpy.data.materials:
251             cmat = mat.cycles
252
253             # Volume Sampling
254             if not cmat.is_property_set("volume_sampling"):
255                 cmat.volume_sampling = 'DISTANCE'
256
257     if bpy.data.version <= (2, 76, 9):
258         for world in bpy.data.worlds:
259             cworld = world.cycles
260
261             # World MIS
262             if not cworld.is_property_set("sample_as_light"):
263                 cworld.sample_as_light = False
264
265             # World MIS Samples
266             if not cworld.is_property_set("samples"):
267                 cworld.samples = 4
268
269             # World MIS Resolution
270             if not cworld.is_property_set("sample_map_resolution"):
271                 cworld.sample_map_resolution = 256
272
273     if bpy.data.version <= (2, 76, 10):
274         for scene in bpy.data.scenes:
275             cscene = scene.cycles
276             if cscene.is_property_set("filter_type"):
277                 if not cscene.is_property_set("pixel_filter_type"):
278                     cscene.pixel_filter_type = cscene.filter_type
279                 if cscene.filter_type == 'BLACKMAN_HARRIS':
280                     cscene.filter_type = 'GAUSSIAN'