def __update_look__(self, context): """Hookup function for triggering update look from material in internal module of looks. It should be used on any property which should be saved in exported into looks. :param context: Blender context :type context: bpy.types.Context """ if hasattr(context, "active_object") and hasattr(context.active_object, "active_material") and context.active_object.active_material: scs_root = _object_utils.get_scs_root(context.active_object) if scs_root: _looks.update_look_from_material(scs_root, context.active_object.active_material, "preset_change" in self)
def execute(self, context): lprint("I " + self.bl_label + "...") from io_scs_tools.internals.shader_presets import cache as _shader_presets_cache from io_scs_tools.utils import get_shader_presets_inventory as _get_shader_presets_inventory mat = context.material mat_scs_props = mat.scs_props """:type: io_scs_tools.properties.material.MaterialSCSTools""" preset = _get_shader_presets_inventory()[mat_scs_props.active_shader_preset_name] """:type: io_scs_tools.properties.world.ShaderPresetsInventoryItem""" # extract only flavor effect part of string flavor_effect_part = mat_scs_props.mat_effect_name[len(preset.effect):] new_flavor_state = not self.flavor_enabled flavors_suffix = "" for flavor in preset.flavors: flavor_variant_found = False for flavor_variant in flavor.variants: if flavor_variant.name == self.flavor_name: # add founded flavor to flavors suffix only if enabled if new_flavor_state: flavors_suffix += "." + flavor_variant.name flavor_variant_found = True break # if one variant of flavor is found skip all other variants if flavor_variant_found: continue # make sure to add all other enabled flavors to flavors suffix for flavor_variant in flavor.variants: is_in_middle = "." + flavor_variant.name + "." in flavor_effect_part is_on_end = flavor_effect_part.endswith("." + flavor_variant.name) if is_in_middle or is_on_end: flavors_suffix += "." + flavor_variant.name # finally set new shader data to material section = _shader_presets_cache.get_section(preset, flavors_suffix) context.material.scs_props.mat_effect_name = preset.effect + flavors_suffix _material_utils.set_shader_data_to_material(context.material, section) # sync shader types on all scs roots by updating looks on them # to avoid different shader types on different scs roots for same material for scs_root in _object_utils.gather_scs_roots(bpy.data.objects): _looks.update_look_from_material(scs_root, mat, True) return {'FINISHED'}
def execute(self, context): lprint("I " + self.bl_label + "...") from io_scs_tools.internals import shader_presets as _shader_presets mat = context.material mat_scs_props = mat.scs_props """:type: io_scs_tools.properties.material.MaterialSCSTools""" preset = _shader_presets.get_preset( mat_scs_props.active_shader_preset_name) # extract only flavor effect part of string flavor_effect_part = mat_scs_props.mat_effect_name[len(preset. effect):] new_flavor_state = not self.flavor_enabled flavors_suffix = "" for flavor in preset.flavors: flavor_variant_found = False for flavor_variant in flavor.variants: if flavor_variant.suffix == self.flavor_name: # add founded flavor to flavors suffix only if enabled if new_flavor_state: flavors_suffix += "." + flavor_variant.suffix flavor_variant_found = True break # if one variant of flavor is found skip all other variants if flavor_variant_found: continue # make sure to add all other enabled flavors to flavors suffix for flavor_variant in flavor.variants: is_in_middle = "." + flavor_variant.suffix + "." in flavor_effect_part is_on_end = flavor_effect_part.endswith( "." + flavor_variant.suffix) if is_in_middle or is_on_end: flavors_suffix += "." + flavor_variant.suffix # if desired combination doesn't exists, abort switching and notify user if not _shader_presets.has_section(preset.name, flavors_suffix): message = "Enabling %r flavor aborted! Wanted shader combination: %r is not supported!" % ( self.flavor_name, preset.effect + flavors_suffix) lprint("E " + message) self.report({'WARNING'}, message) return {'FINISHED'} # finally set new shader data to material section = _shader_presets.get_section(preset.name, flavors_suffix) context.material.scs_props.mat_effect_name = preset.effect + flavors_suffix _material_utils.set_shader_data_to_material( context.material, section) # sync shader types on all scs roots by updating looks on them # to avoid different shader types on different scs roots for same material for scs_root in _object_utils.gather_scs_roots(bpy.data.objects): _looks.update_look_from_material(scs_root, mat, True) return {'FINISHED'}
def execute(self, context): # find group names created by Blender Tools with # dynamic importing of all modules from "internals/shaders" folder # and checking if module has "get_node_group" functions which indicates that # module creates node group groups_to_remove = [ "AddEnvGroup", # from v0.6 "FresnelGroup", # from v0.6 "LampmaskMixerGroup", # from v0.6 "ReflectionNormalGroup", # from v0.6 ] for root, dirs, files in os.walk( _path_utils.get_addon_installation_paths()[0] + os.sep + "internals/shaders"): for file in files: if not file.endswith(".py"): continue module = SourceFileLoader(root + os.sep + file, root + os.sep + file).load_module() if "get_node_group" in dir(module): ng = module.get_node_group() groups_to_remove.append(ng.name) # 1. clear nodes on materials for mat in bpy.data.materials: if not mat.node_tree: continue # also check none blender tools materials just to remove possible nodes usage of our groups if mat.scs_props.active_shader_preset_name == "<none>": nodes_to_remove = [] # check for possible leftover usage of our node groups for node in mat.node_tree.nodes: # filter out nodes which are not node group and node groups without node tree if node.type != "GROUP" or not node.node_tree: continue if node.node_tree.name in groups_to_remove: nodes_to_remove.append(node.node_tree.name) # remove possible leftover used node group nodes for node_name in nodes_to_remove: mat.node_tree.nodes.remove( mat.node_tree.nodes[node_name]) continue mat.node_tree.nodes.clear() # 2. clear nodes on node groups for ng_name in groups_to_remove: if ng_name not in bpy.data.node_groups: continue ng = bpy.data.node_groups[ng_name] ng.nodes.clear() # 3. remove node groups from blender data blocks for ng_name in groups_to_remove: if ng_name not in bpy.data.node_groups: continue bpy.data.node_groups.remove(bpy.data.node_groups[ng_name], do_unlink=True) # 4. finally set preset to material again, which will update nodes and possible input interface changes scs_roots = _object_utils.gather_scs_roots(bpy.data.objects) for mat in bpy.data.materials: # ignore none blender tools materials if mat.scs_props.active_shader_preset_name == "<none>": continue material_textures = {} if "scs_shader_attributes" in mat and "textures" in mat[ "scs_shader_attributes"]: for texture in mat["scs_shader_attributes"][ "textures"].values(): tex_id = texture["Tag"].split(":")[1] tex_value = texture["Value"] material_textures[tex_id] = tex_value (preset_name, preset_section) = _material_utils.find_preset( mat.scs_props.mat_effect_name, material_textures) if preset_section: _material_utils.set_shader_data_to_material( mat, preset_section) # sync shader types on all scs roots by updating looks on them # without this call we might end up with outdated looks raising errors once user will switch to them for scs_root in scs_roots: _looks.update_look_from_material(scs_root, mat, True) return {'FINISHED'}