diff options
-rw-r--r-- | intern/cycles/blender/addon/version_update.py | 450 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_ID.c | 14 |
2 files changed, 213 insertions, 251 deletions
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py index 3a4b13ef9d2..f3d60d62e02 100644 --- a/intern/cycles/blender/addon/version_update.py +++ b/intern/cycles/blender/addon/version_update.py @@ -22,89 +22,39 @@ import math from bpy.app.handlers import persistent -def check_is_new_shading_ntree(node_tree): - for node in node_tree.nodes: - # If material has any node with ONLY new shading system - # compatibility then it's considered a Cycles material - # and versioning code would need to perform on it. - # - # We can not check for whether NEW_SHADING in compatibility - # because some nodes could have compatibility with both old - # and new shading system and they can't be used for any - # decision here. - if node.shading_compatibility == {'NEW_SHADING'}: - return True - - # If node is only compatible with old shading system - # then material can not be Cycles material and we - # can stopiterating nodes now. - if node.shading_compatibility == {'OLD_SHADING'}: - return False - return False - - -def check_is_new_shading_material(material): - if not material.node_tree: - return False - return check_is_new_shading_ntree(material.node_tree) - - -def check_is_new_shading_world(world): - if not world.node_tree: - return False - return check_is_new_shading_ntree(world.node_tree) - - -def check_is_new_shading_lamp(lamp): - if not lamp.node_tree: - return False - return check_is_new_shading_ntree(lamp.node_tree) - - -def foreach_notree_node(nodetree, callback, traversed): - if nodetree in traversed: - return - traversed.add(nodetree) +def foreach_cycles_nodetree_group(nodetree, traversed): for node in nodetree.nodes: - callback(node) if node.bl_idname == 'ShaderNodeGroup': - foreach_notree_node(node.node_tree, callback, traversed) + group = node.node_tree + if group and group not in traversed: + traversed.add(group) + yield group, group.library + yield from foreach_cycles_nodetree_group(group, traversed) -def foreach_cycles_node(callback): +def foreach_cycles_nodetree(): traversed = set() + for material in bpy.data.materials: - if check_is_new_shading_material(material): - foreach_notree_node( - material.node_tree, - callback, - traversed, - ) + nodetree = material.node_tree + if nodetree: + yield nodetree, material.library + yield from foreach_cycles_nodetree_group(nodetree, traversed) + for world in bpy.data.worlds: - if check_is_new_shading_world(world): - foreach_notree_node( - world.node_tree, - callback, - traversed, - ) - for lamp in bpy.data.lamps: - if check_is_new_shading_world(lamp): - foreach_notree_node( - lamp.node_tree, - callback, - traversed, - ) + nodetree = world.node_tree + if nodetree: + yield nodetree, world.library + foreach_cycles_nodetree_group(nodetree, traversed) + for lamp in bpy.data.lamps: + nodetree = lamp.node_tree + if nodetree: + yield nodetree, lamp.library + foreach_cycles_nodetree_group(nodetree, traversed) -def displacement_node_insert(material, nodetree, traversed): - if nodetree in traversed: - return - traversed.add(nodetree) - - for node in nodetree.nodes: - if node.bl_idname == 'ShaderNodeGroup': - displacement_node_insert(material, node.node_tree, traversed) +def displacement_node_insert(nodetree): # Gather links to replace displacement_links = [] for link in nodetree.links: @@ -134,12 +84,6 @@ def displacement_node_insert(material, nodetree, traversed): nodetree.links.new(node.outputs['Displacement'], to_socket) -def displacement_nodes_insert(): - traversed = set() - for material in bpy.data.materials: - if check_is_new_shading_material(material): - displacement_node_insert(material, material.node_tree, traversed) - def displacement_principled_nodes(node): if node.bl_idname == 'ShaderNodeDisplacement': @@ -150,11 +94,7 @@ def displacement_principled_nodes(node): node.subsurface_method = 'BURLEY' -def square_roughness_node_insert(material, nodetree, traversed): - if nodetree in traversed: - return - traversed.add(nodetree) - +def square_roughness_node_insert(nodetree): roughness_node_types = { 'ShaderNodeBsdfAnisotropic', 'ShaderNodeBsdfGlass', @@ -163,9 +103,7 @@ def square_roughness_node_insert(material, nodetree, traversed): # Update default values for node in nodetree.nodes: - if node.bl_idname == 'ShaderNodeGroup': - square_roughness_node_insert(material, node.node_tree, traversed) - elif node.bl_idname in roughness_node_types: + if node.bl_idname in roughness_node_types: roughness_input = node.inputs['Roughness'] roughness_input.default_value = math.sqrt(max(roughness_input.default_value, 0.0)) @@ -195,13 +133,6 @@ def square_roughness_node_insert(material, nodetree, traversed): nodetree.links.new(node.outputs['Value'], to_socket) -def square_roughness_nodes_insert(): - traversed = set() - for material in bpy.data.materials: - if check_is_new_shading_material(material): - square_roughness_node_insert(material, material.node_tree, traversed) - - def mapping_node_order_flip(node): """ Flip euler order of mapping shader node @@ -283,18 +214,12 @@ def custom_bake_remap(scene): scene.render.bake.use_pass_indirect = False -def ambient_occlusion_node_relink(material, nodetree, traversed): - if nodetree in traversed: - return - traversed.add(nodetree) - +def ambient_occlusion_node_relink(nodetree): for node in nodetree.nodes: if node.bl_idname == 'ShaderNodeAmbientOcclusion': node.samples = 1 node.only_local = False node.inputs['Distance'].default_value = 0.0 - elif node.bl_idname == 'ShaderNodeGroup': - ambient_occlusion_node_relink(material, node.node_tree, traversed) # Gather links to replace ao_links = [] @@ -311,13 +236,6 @@ def ambient_occlusion_node_relink(material, nodetree, traversed): nodetree.links.new(from_node.outputs['Color'], to_socket) -def ambient_occlusion_nodes_relink(): - traversed = set() - for material in bpy.data.materials: - if check_is_new_shading_material(material): - ambient_occlusion_node_relink(material, material.node_tree, traversed) - - @persistent def do_versions(self): if bpy.context.user_preferences.version <= (2, 78, 1): @@ -343,156 +261,186 @@ def do_versions(self): if not bpy.data.is_saved: return - # Clamp Direct/Indirect separation in 270 - if bpy.data.version <= (2, 70, 0): - for scene in bpy.data.scenes: - cscene = scene.cycles - sample_clamp = cscene.get("sample_clamp", False) - if ( - sample_clamp and - not cscene.is_property_set("sample_clamp_direct") and - not cscene.is_property_set("sample_clamp_indirect") - ): - - cscene.sample_clamp_direct = sample_clamp - cscene.sample_clamp_indirect = sample_clamp - - # Change of Volume Bounces in 271 - if bpy.data.version <= (2, 71, 0): - for scene in bpy.data.scenes: - cscene = scene.cycles - if not cscene.is_property_set("volume_bounces"): - cscene.volume_bounces = 1 + # Map of versions used by libraries. + library_versions = {} + library_versions[bpy.data.version] = [None] + for library in bpy.data.libraries: + library_versions.setdefault(library.version, []).append(library) - # Caustics Reflective/Refractive separation in 272 - if bpy.data.version <= (2, 72, 0): - for scene in bpy.data.scenes: - cscene = scene.cycles - if ( - cscene.get("no_caustics", False) and - not cscene.is_property_set("caustics_reflective") and - not cscene.is_property_set("caustics_refractive") - ): - cscene.caustics_reflective = False - cscene.caustics_refractive = False - - # Euler order was ZYX in previous versions. - if bpy.data.version <= (2, 73, 4): - foreach_cycles_node(mapping_node_order_flip) - - if bpy.data.version <= (2, 76, 5): - foreach_cycles_node(vector_curve_node_remap) - - # Baking types changed - if bpy.data.version <= (2, 76, 6): - for scene in bpy.data.scenes: - custom_bake_remap(scene) + # Do versioning per library, since they might have different versions. + max_need_versioning = (2, 79, 6) + for version, libraries in library_versions.items(): + if version > max_need_versioning: + continue - # Several default changes for 2.77 - if bpy.data.version <= (2, 76, 8): + # Scenes for scene in bpy.data.scenes: - cscene = scene.cycles - - # Samples - if not cscene.is_property_set("samples"): - cscene.samples = 10 - - # Preview Samples - if not cscene.is_property_set("preview_samples"): - cscene.preview_samples = 10 - - # Filter - if not cscene.is_property_set("filter_type"): - cscene.pixel_filter_type = 'GAUSSIAN' - - # Tile Order - if not cscene.is_property_set("tile_order"): - cscene.tile_order = 'CENTER' - + if scene.library not in libraries: + continue + + # Clamp Direct/Indirect separation in 270 + if version <= (2, 70, 0): + cscene = scene.cycles + sample_clamp = cscene.get("sample_clamp", False) + if ( + sample_clamp and + not cscene.is_property_set("sample_clamp_direct") and + not cscene.is_property_set("sample_clamp_indirect") + ): + + cscene.sample_clamp_direct = sample_clamp + cscene.sample_clamp_indirect = sample_clamp + + # Change of Volume Bounces in 271 + if version <= (2, 71, 0): + cscene = scene.cycles + if not cscene.is_property_set("volume_bounces"): + cscene.volume_bounces = 1 + + # Caustics Reflective/Refractive separation in 272 + if version <= (2, 72, 0): + cscene = scene.cycles + if ( + cscene.get("no_caustics", False) and + not cscene.is_property_set("caustics_reflective") and + not cscene.is_property_set("caustics_refractive") + ): + cscene.caustics_reflective = False + cscene.caustics_refractive = False + + # Baking types changed + if version <= (2, 76, 6): + custom_bake_remap(scene) + + # Several default changes for 2.77 + if version <= (2, 76, 8): + cscene = scene.cycles + + # Samples + if not cscene.is_property_set("samples"): + cscene.samples = 10 + + # Preview Samples + if not cscene.is_property_set("preview_samples"): + cscene.preview_samples = 10 + + # Filter + if not cscene.is_property_set("filter_type"): + cscene.pixel_filter_type = 'GAUSSIAN' + + # Tile Order + if not cscene.is_property_set("tile_order"): + cscene.tile_order = 'CENTER' + + if version <= (2, 76, 10): + cscene = scene.cycles + if cscene.is_property_set("filter_type"): + if not cscene.is_property_set("pixel_filter_type"): + cscene.pixel_filter_type = cscene.filter_type + if cscene.filter_type == 'BLACKMAN_HARRIS': + cscene.filter_type = 'GAUSSIAN' + + if version <= (2, 78, 2): + cscene = scene.cycles + if not cscene.is_property_set("light_sampling_threshold"): + cscene.light_sampling_threshold = 0.0 + + if version <= (2, 79, 0): + cscene = scene.cycles + # Default changes + if not cscene.is_property_set("aa_samples"): + cscene.aa_samples = 4 + if not cscene.is_property_set("preview_aa_samples"): + cscene.preview_aa_samples = 4 + if not cscene.is_property_set("blur_glossy"): + cscene.blur_glossy = 0.0 + if not cscene.is_property_set("sample_clamp_indirect"): + cscene.sample_clamp_indirect = 0.0 + + # Lamps for lamp in bpy.data.lamps: - clamp = lamp.cycles - - # MIS - if not clamp.is_property_set("use_multiple_importance_sampling"): - clamp.use_multiple_importance_sampling = False + if lamp.library not in libraries: + continue - for mat in bpy.data.materials: - cmat = mat.cycles + if version <= (2, 76, 5): + clamp = lamp.cycles - # Volume Sampling - if not cmat.is_property_set("volume_sampling"): - cmat.volume_sampling = 'DISTANCE' + # MIS + if not clamp.is_property_set("use_multiple_importance_sampling"): + clamp.use_multiple_importance_sampling = False - if bpy.data.version <= (2, 76, 9): + # Worlds for world in bpy.data.worlds: - cworld = world.cycles - - # World MIS Samples - if not cworld.is_property_set("samples"): - cworld.samples = 4 - - # World MIS Resolution - if not cworld.is_property_set("sample_map_resolution"): - cworld.sample_map_resolution = 256 - - if bpy.data.version <= (2, 76, 10): - for scene in bpy.data.scenes: - cscene = scene.cycles - if cscene.is_property_set("filter_type"): - if not cscene.is_property_set("pixel_filter_type"): - cscene.pixel_filter_type = cscene.filter_type - if cscene.filter_type == 'BLACKMAN_HARRIS': - cscene.filter_type = 'GAUSSIAN' - - if bpy.data.version <= (2, 78, 2): - for scene in bpy.data.scenes: - cscene = scene.cycles - if not cscene.is_property_set("light_sampling_threshold"): - cscene.light_sampling_threshold = 0.0 - - if bpy.data.version <= (2, 79, 0): - for scene in bpy.data.scenes: - cscene = scene.cycles - # Default changes - if not cscene.is_property_set("aa_samples"): - cscene.aa_samples = 4 - if not cscene.is_property_set("preview_aa_samples"): - cscene.preview_aa_samples = 4 - if not cscene.is_property_set("blur_glossy"): - cscene.blur_glossy = 0.0 - if not cscene.is_property_set("sample_clamp_indirect"): - cscene.sample_clamp_indirect = 0.0 - - if bpy.data.version <= (2, 79, 1): - displacement_nodes_insert() - - if bpy.data.version <= (2, 79, 2): + if world.library not in libraries: + continue + + if version <= (2, 76, 9): + cworld = world.cycles + + # World MIS Samples + if not cworld.is_property_set("samples"): + cworld.samples = 4 + + # World MIS Resolution + if not cworld.is_property_set("sample_map_resolution"): + cworld.sample_map_resolution = 256 + + if version <= (2, 79, 4): + cworld = world.cycles + # World MIS + if not cworld.is_property_set("sampling_method"): + if cworld.get("sample_as_light", True): + cworld.sampling_method = 'MANUAL' + else: + cworld.sampling_method = 'NONE' + + # Materials for mat in bpy.data.materials: - cmat = mat.cycles - if not cmat.is_property_set("displacement_method"): - cmat.displacement_method = 'BUMP' - - foreach_cycles_node(displacement_principled_nodes) + if mat.library not in libraries: + continue + + if version <= (2, 76, 5): + cmat = mat.cycles + # Volume Sampling + if not cmat.is_property_set("volume_sampling"): + cmat.volume_sampling = 'DISTANCE' + + if version <= (2, 79, 2): + cmat = mat.cycles + if not cmat.is_property_set("displacement_method"): + cmat.displacement_method = 'BUMP' + + # Change default to bump again. + if version <= (2, 79, 6): + cmat = mat.cycles + if not cmat.is_property_set("displacement_method"): + cmat.displacement_method = 'DISPLACEMENT' + + # Nodes + for nodetree, library in foreach_cycles_nodetree(): + if library not in libraries: + continue + + # Euler order was ZYX in previous versions. + if version <= (2, 73, 4): + for node in nodetree.nodes: + mapping_node_order_flip(node) + + if version <= (2, 76, 5): + for node in nodetree.nodes: + vector_curve_node_remap(node) + + if version <= (2, 79, 1): + displacement_node_insert(nodetree) + + if version <= (2, 79, 2): + for node in nodetree.nodes: + displacement_principled_nodes(node) + + if version <= (2, 79, 3): + # Switch to squared roughness convention + square_roughness_node_insert(nodetree) + + if version <= (2, 79, 4): + ambient_occlusion_node_relink(nodetree) - if bpy.data.version <= (2, 79, 3): - # Switch to squared roughness convention - square_roughness_nodes_insert() - - if bpy.data.version <= (2, 79, 4): - for world in bpy.data.worlds: - cworld = world.cycles - # World MIS - if not cworld.is_property_set("sampling_method"): - if cworld.get("sample_as_light", True): - cworld.sampling_method = 'MANUAL' - else: - cworld.sampling_method = 'NONE' - - ambient_occlusion_nodes_relink() - - if bpy.data.version <= (2, 79, 6): - # Change default to bump again. - for mat in bpy.data.materials: - cmat = mat.cycles - if not cmat.is_property_set("displacement_method"): - cmat.displacement_method = 'DISPLACEMENT' diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 3a22782f31e..85b1ec4d958 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -762,6 +762,14 @@ static IDProperty *rna_IDPropertyWrapPtr_idprops(PointerRNA *ptr, bool UNUSED(cr return ptr->data; } +static void rna_Library_version_get(PointerRNA *ptr, int *value) +{ + Library *lib = (Library *)ptr->data; + value[0] = lib->versionfile / 100; + value[1] = lib->versionfile % 100; + value[2] = lib->subversionfile; +} + #else static void rna_def_ID_properties(BlenderRNA *brna) @@ -1110,6 +1118,12 @@ static void rna_def_library(BlenderRNA *brna) RNA_def_property_pointer_sdna(prop, NULL, "packedfile"); RNA_def_property_ui_text(prop, "Packed File", ""); + prop = RNA_def_int_vector(srna, "version", 3, NULL, 0, INT_MAX, + "Version", "Version of Blender the library .blend was saved with", 0, INT_MAX); + RNA_def_property_int_funcs(prop, "rna_Library_version_get", NULL, NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_flag(prop, PROP_THICK_WRAP); + func = RNA_def_function(srna, "reload", "WM_lib_reload"); RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT); RNA_def_function_ui_description(func, "Reload this library and all its linked data-blocks"); |