def set_shader_presets_item(self, value): """ Receives an actual index of currently selected Shader preset name in the menu, sets that Shader name as active in active Material. :param value: :return: """ material = bpy.context.active_object.active_material if value == 0: # No Shader... material.scs_props.active_shader_preset_name = "<none>" material.scs_props.mat_effect_name = "None" # reset material nodes when user selects none shader if material.node_tree: material.node_tree.nodes.clear() material.use_nodes = False material["scs_shader_attributes"] = {} else: for preset_i, preset in enumerate(_get_shader_presets_inventory()): if value == preset_i: # Set Shader Preset in the Material preset_section = _material_utils.get_shader_preset( _get_scs_globals().shader_presets_filepath, preset.name) if preset_section: preset_name = preset_section.get_prop_value( "PresetName") preset_effect = preset_section.get_prop_value("Effect") material.scs_props.mat_effect_name = preset_effect if preset_name: _material_utils.set_shader_data_to_material( material, preset_section) material.scs_props.active_shader_preset_name = preset_name else: material.scs_props.active_shader_preset_name = "<none>" material["scs_shader_attributes"] = {} print(' NO "preset_name"!') # if preset_effect: # print(' preset_effect: "%s"' % preset_effect) # if preset_flags: # print(' preset_flags: "%s"' % preset_flags) # if preset_attribute_cnt: # print(' preset_attribute_cnt: "%s"' % preset_attribute_cnt) # if preset_texture_cnt: # print(' preset_texture_cnt: "%s"' % preset_texture_cnt) else: print('''NO "preset_section"! (Shouldn't happen!)''') else: preset.active = False
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.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) return {'FINISHED'}
def set_shader_presets_item(self, value): """ Receives an actual index of currently selected Shader preset name in the menu, sets that Shader name as active in active Material. :param value: :return: """ material = bpy.context.active_object.active_material if value == 0: # No Shader... material.scs_props.active_shader_preset_name = "<none>" material.scs_props.mat_effect_name = "None" material["scs_shader_attributes"] = {} else: for preset_i, preset in enumerate(bpy.data.worlds[0].scs_shader_presets_inventory): if value == preset_i: # Set Shader Preset in the Material preset_section = _material_utils.get_shader_preset(_get_scs_globals().shader_presets_filepath, preset.name) if preset_section: preset_name = preset_section.get_prop_value("PresetName") preset_effect = preset_section.get_prop_value("Effect") material.scs_props.mat_effect_name = preset_effect if preset_name: _material_utils.set_shader_data_to_material(material, preset_section, preset_effect) material.scs_props.active_shader_preset_name = preset_name else: material.scs_props.active_shader_preset_name = "<none>" material["scs_shader_attributes"] = {} print(' NO "preset_name"!') # if preset_effect: # print(' preset_effect: "%s"' % preset_effect) # if preset_flags: # print(' preset_flags: "%s"' % preset_flags) # if preset_attribute_cnt: # print(' preset_attribute_cnt: "%s"' % preset_attribute_cnt) # if preset_texture_cnt: # print(' preset_texture_cnt: "%s"' % preset_texture_cnt) else: print('''NO "preset_section"! (Shouldn't happen!)''') else: preset.active = False
def _create_scs_root_object(name, loaded_variants, loaded_looks, mats_info, objects, locators, armature): """Creates an 'SCS Root Object' (Empty Object) for currently imported 'SCS Game Object' and parent all import content to it. :param name: :type name: str :param loaded_variants: X :type loaded_variants: list :param loaded_looks: X :type loaded_looks: list :param mats_info: list of material info, one material info consists of list: [ blend_mat_name, mat_effect, original_mat_alias ] :type mats_info: list of list :param objects: X :type objects: list :param locators: X :type locators: list :param armature: Armature Object :type armature: bpy.types.Object :return: SCS Root Object :rtype: bpy.types.Object """ context = bpy.context # MAKE THE 'SCS ROOT OBJECT' NAME UNIQUE name = _name_utils.get_unique(name, bpy.data.objects) # CREATE EMPTY OBJECT & MAKE A PROPER SETTINGS TO THE 'SCS Game Object' OBJECT scs_root_object = bpy.data.objects.new(name, None) bpy.context.view_layer.active_layer_collection.collection.objects.link( scs_root_object) bpy.context.view_layer.objects.active = scs_root_object scs_root_object.scs_props.scs_root_object_export_enabled = True scs_root_object.scs_props.empty_object_type = 'SCS_Root' # print('LOD.pos: %s' % str(scs_root_object.location)) # print('CUR.pos: %s' % str(context.space_data.cursor_location)) # PARENTING bpy.ops.object.select_all(action='DESELECT') if armature: # if armature is present we can specify our game object as animated scs_root_object.scs_props.scs_root_animated = "anim" # print('ARM.pos: %s' % str(armature.location)) armature.select_set(True) armature.scs_props.parent_identity = scs_root_object.name for obj in objects: # print('OBJ.pos: %s' % str(object.location)) obj.select_set(True) obj.scs_props.parent_identity = scs_root_object.name for obj in locators: obj.select_set(True) obj.scs_props.parent_identity = scs_root_object.name bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) bpy.ops.object.parent_clear(type='CLEAR_INVERSE') # LOCATION scs_root_object.location = context.scene.cursor.location # MAKE ONLY 'SCS GAME OBJECT' SELECTED bpy.ops.object.select_all(action='DESELECT') scs_root_object.select_set(True) context.view_layer.objects.active = scs_root_object # MAKE PART RECORD part_inventory = scs_root_object.scs_object_part_inventory parts_dict = _object_utils.collect_parts_on_root(scs_root_object) for part_name in parts_dict: _inventory.add_item(part_inventory, part_name) # MAKE VARIANT RECORD variant_inventory = scs_root_object.scs_object_variant_inventory for variant_i, variant_record in enumerate(loaded_variants): variant_name = variant_record[0] variantparts = variant_record[1] variant = _inventory.add_item(variant_inventory, variant_name) # for every variant create all of the part entries and mark them included properly for part in part_inventory: part = _inventory.add_item(variant.parts, part.name) if part.name in variantparts: part.include = True # cleanup generated terrain points vertex layers by variant for obj in parts_dict[part.name]: if obj.type != "MESH": continue vg_to_delete = [] accepted_vg_nodes = {} for vertex_group in obj.vertex_groups: # ignore any vertex group which isn't from terrain points # (others might come from skinning) if _OP_consts.TerrainPoints.vg_name_prefix not in vertex_group.name: continue # ignore already fixed vertex group if vertex_group.name.startswith( _OP_consts.TerrainPoints.vg_name_prefix): continue # get variant index from first 6 chars -> check PIM importer for more info vg_var_index = int(vertex_group.name[:6]) # ignore other variant vertex groups and add them to delete list if vg_var_index >= 0 and vg_var_index != variant_i: vg_to_delete.append(vertex_group) continue # finally remove variant prefixing name if variant is not defined (-1) # or index matches current one vertex_group.name = vertex_group.name[6:] # log accepted node index for identifying which vertex groups # really have to be deleted accepted_vg_nodes[vertex_group.name[-1]] = 1 # cleanup possible duplicates for the same node # because one object anyway can not have terrain points vertex groups for multiple variants while len(vg_to_delete) > 0 and len(accepted_vg_nodes) > 0: curr_vg = vg_to_delete.pop() # extra caution step where group can be deleted # only if one of vertex groups for this node was accepted if curr_vg.name[-1] in accepted_vg_nodes: obj.vertex_groups.remove(curr_vg) else: part.include = False # MAKE LOOK RECORDS for look_i, look in enumerate(loaded_looks): look_name = look[0] look_mat_settings = look[1] # setup all the materials. NOTE: They should be already created by PIM import. for mat_info in mats_info: mat = bpy.data.materials[mat_info[0]] if mat_info[2] in look_mat_settings: # extract imported shader data material_effect, material_attributes, material_textures, material_section = _get_shader_data( look_mat_settings[mat_info[2]]) # try to find suitable preset (preset_name, preset_section) = _material_utils.find_preset( material_effect, material_textures) # we don't support effect mismatch between looks, even if game works with it, somehow. # most probably imported model is result of third party software, thus let user know and skip look for this material if look_i != 0 and material_effect != mat.scs_props.mat_effect_name: lprint( "E Look %r skipped on material %r, mismatched material effect: %r but should be %r.", (look_name, mat.name, material_effect, mat.scs_props.mat_effect_name)) continue # preset name is found & shader data are compatible with found preset if preset_name and _are_shader_data_compatible( preset_section, material_attributes, material_textures, mat_info[0]): mat.scs_props.active_shader_preset_name = preset_name if preset_section: preset_effect = preset_section.get_prop_value("Effect") mat.scs_props.mat_effect_name = preset_effect if look_i == 0: # apply default shader settings _material_utils.set_shader_data_to_material( mat, preset_section, is_import=True) # reapply settings from material _material_utils.set_shader_data_to_material( mat, material_section, is_import=True, override_back_data=False) lprint("D Using shader preset on material %r.", (mat.name, )) else: print('''NO "preset_section"! (Shouldn't happen!)''') else: # import shader directly from material and mark it as imported mat.scs_props.active_shader_preset_name = "<imported>" _material_utils.set_shader_data_to_material( mat, material_section, is_import=True) lprint( "W Using imported shader on material %r, effect: %r.", (mat.name, mat.scs_props.mat_effect_name)) if look_i == len(loaded_looks) - 1: # delete not needed data on material if "scs_tex_aliases" in mat: del mat["scs_tex_aliases"] # create new look entry on root bpy.ops.object.scs_tools_add_look(look_name=look_name, instant_apply=False) # apply first look after everything is done scs_root_object.scs_props.active_scs_look = 0 # fix scs root children objects count so it won't trigger persistent cycle scs_root_object.scs_cached_num_children = len(scs_root_object.children) return scs_root_object
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'}
def _create_scs_root_object(name, loaded_variants, loaded_looks, mats_info, objects, locators, armature): """Creates an 'SCS Root Object' (Empty Object) for currently imported 'SCS Game Object' and parent all import content to it. :param name: :type name: str :param loaded_variants: X :type loaded_variants: list :param loaded_looks: X :type loaded_looks: list :param mats_info: list of material info, one material info consists of list: [ blend_mat_name, mat_effect, original_mat_alias ] :type mats_info: list of list :param objects: X :type objects: list :param locators: X :type locators: list :param armature: Armature Object :type armature: bpy.types.Object :return: SCS Root Object :rtype: bpy.types.Object """ context = bpy.context # MAKE THE 'SCS ROOT OBJECT' NAME UNIQUE name = _name_utils.get_unique(name, bpy.data.objects) # CREATE EMPTY OBJECT bpy.ops.object.empty_add( view_align=False, location=(0.0, 0.0, 0.0), # rotation=rot, ) # , layers=(False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, # False, False)) # MAKE A PROPER SETTINGS TO THE 'SCS Game Object' OBJECT scs_root_object = context.active_object scs_root_object.name = name scs_root_object.scs_props.scs_root_object_export_enabled = True scs_root_object.scs_props.empty_object_type = 'SCS_Root' # print('LOD.pos: %s' % str(scs_root_object.location)) # print('CUR.pos: %s' % str(context.space_data.cursor_location)) # PARENTING if armature: # if armature is present we can specify our game object as animated scs_root_object.scs_props.scs_root_animated = "anim" # print('ARM.pos: %s' % str(armature.location)) bpy.ops.object.select_all(action='DESELECT') armature.select = True bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) armature.scs_props.parent_identity = scs_root_object.name for obj in objects: # print('OBJ.pos: %s' % str(object.location)) bpy.ops.object.select_all(action='DESELECT') obj.select = True bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) obj.scs_props.parent_identity = scs_root_object.name for obj in locators: bpy.ops.object.select_all(action='DESELECT') obj.select = True bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) obj.scs_props.parent_identity = scs_root_object.name # LOCATION scs_root_object.location = context.scene.cursor_location # MAKE ONLY 'SCS GAME OBJECT' SELECTED bpy.ops.object.select_all(action='DESELECT') for obj in bpy.data.objects: obj.select = False scs_root_object.select = True context.scene.objects.active = scs_root_object # MAKE PART RECORD part_inventory = scs_root_object.scs_object_part_inventory parts_dict = _object_utils.collect_parts_on_root(scs_root_object) for part_name in parts_dict: _inventory.add_item(part_inventory, part_name) # MAKE VARIANT RECORD variant_inventory = scs_root_object.scs_object_variant_inventory for variant_i, variant_record in enumerate(loaded_variants): variant_name = variant_record[0] variantparts = variant_record[1] variant = _inventory.add_item(variant_inventory, variant_name) # for every variant create all of the part entries and mark them included properly for part in part_inventory: part = _inventory.add_item(variant.parts, part.name) if part.name in variantparts: part.include = True # cleanup generated terrain points vertex layers by variant for obj in parts_dict[part.name]: if obj.type != "MESH": continue vg_to_delete = [] accepted_vg_nodes = {} for vertex_group in obj.vertex_groups: # ignore any vertex group which isn't from terrain points # (others might come from skinning) if _OP_consts.TerrainPoints.vg_name_prefix not in vertex_group.name: continue # ignore already fixed vertex group if vertex_group.name.startswith(_OP_consts.TerrainPoints.vg_name_prefix): continue # get variant index from first 6 chars -> check PIM importer for more info vg_var_index = int(vertex_group.name[:6]) # ignore other variant vertex groups and add them to delete list if vg_var_index >= 0 and vg_var_index != variant_i: vg_to_delete.append(vertex_group) continue # finally remove variant prefixing name if variant is not defined (-1) # or index matches current one vertex_group.name = vertex_group.name[6:] # log accepted node index for identifying which vertex groups # really have to be deleted accepted_vg_nodes[vertex_group.name[-1]] = 1 # cleanup possible duplicates for the same node # because one object anyway can not have terrain points vertex groups for multiple variants while len(vg_to_delete) > 0 and len(accepted_vg_nodes) > 0: curr_vg = vg_to_delete.pop() # extra caution step where group can be deleted # only if one of vertex groups for this node was accepted if curr_vg.name[-1] in accepted_vg_nodes: obj.vertex_groups.remove(curr_vg) else: part.include = False # MAKE LOOK RECORDS for look_i, look in enumerate(loaded_looks): look_name = look[0] look_mat_settings = look[1] # SETUP ALL THE MATERIALS, NOTE: They should be already created by PIM import. for mat_info in mats_info: mat = bpy.data.materials[mat_info[0]] if mat_info[2] in look_mat_settings: # ASSIGN IMPORTED SHADER DATA material_effect, material_attributes, material_textures, material_section = _get_shader_data(look_mat_settings[mat_info[2]]) # TRY TO FIND SUITABLE PRESET (preset_name, preset_section) = _material_utils.find_preset(material_effect, material_textures) if preset_name: # preset name is found within presets shaders mat.scs_props.active_shader_preset_name = preset_name if preset_section: preset_effect = preset_section.get_prop_value("Effect") mat.scs_props.mat_effect_name = preset_effect if look_i == 0: # apply default shader settings _material_utils.set_shader_data_to_material(mat, preset_section, is_import=True) # reapply settings from material _material_utils.set_shader_data_to_material(mat, material_section, is_import=True, override_back_data=False) lprint("D Using shader preset on material %r.", (mat.name,)) else: print('''NO "preset_section"! (Shouldn't happen!)''') else: # import shader directly from material and mark it as imported mat.scs_props.active_shader_preset_name = "<imported>" _material_utils.set_shader_data_to_material(mat, material_section, is_import=True) lprint("W Using imported shader on material %r, effect: %r.", (mat.name, mat.scs_props.mat_effect_name)) if look_i == len(loaded_looks) - 1: # delete not needed data on material if "scs_tex_aliases" in mat: del mat["scs_tex_aliases"] # CREATE NEW LOOK ENTRY ON ROOT bpy.ops.object.add_scs_look(look_name=look_name, instant_apply=False) # apply first look after everything is done scs_root_object.scs_props.active_scs_look = 0 # fix scs root children objects count so it won't trigger persistent cycle scs_root_object.scs_cached_num_children = len(scs_root_object.children) return scs_root_object
def _create_scs_root_object(name, loaded_variants, loaded_looks, mats_info, objects, skinned_objects, locators, armature): """Creates an 'SCS Root Object' (Empty Object) for currently imported 'SCS Game Object' and parent all import content to it. :param name: :type name: str :param loaded_variants: X :type loaded_variants: list :param loaded_looks: X :type loaded_looks: list :param mats_info: list of material info, one material info consists of list: [ blend_mat_name, mat_effect, original_mat_alias ] :type mats_info: list of list :param objects: X :type objects: list :param skinned_objects: X :type skinned_objects: list :param locators: X :type locators: list :param armature: Armature Object :type armature: bpy.types.Object :return: SCS Root Object :rtype: bpy.types.Object """ context = bpy.context # MAKE THE 'SCS ROOT OBJECT' NAME UNIQUE name = _name_utils.get_unique(name, bpy.data.objects) # CREATE EMPTY OBJECT bpy.ops.object.empty_add( view_align=False, location=(0.0, 0.0, 0.0), # rotation=rot, ) # , layers=(False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, # False, False)) # MAKE A PROPER SETTINGS TO THE 'SCS Game Object' OBJECT scs_root_object = context.active_object scs_root_object.name = name scs_root_object.scs_props.scs_root_object_export_enabled = True scs_root_object.scs_props.empty_object_type = 'SCS_Root' # print('LOD.pos: %s' % str(scs_root_object.location)) # print('CUR.pos: %s' % str(context.space_data.cursor_location)) # PARENTING if armature: # if armature is present we can specify our game object as animated scs_root_object.scs_props.scs_root_animated = "anim" # print('ARM.pos: %s' % str(armature.location)) bpy.ops.object.select_all(action='DESELECT') armature.select = True bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) armature.scs_props.parent_identity = scs_root_object.name for obj in objects: if obj not in skinned_objects: # print('OBJ.pos: %s' % str(object.location)) bpy.ops.object.select_all(action='DESELECT') obj.select = True bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) obj.scs_props.parent_identity = scs_root_object.name for obj in locators: bpy.ops.object.select_all(action='DESELECT') obj.select = True bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) obj.scs_props.parent_identity = scs_root_object.name # LOCATION scs_root_object.location = context.scene.cursor_location # MAKE ONLY 'SCS GAME OBJECT' SELECTED bpy.ops.object.select_all(action='DESELECT') for obj in bpy.data.objects: obj.select = False scs_root_object.select = True context.scene.objects.active = scs_root_object # MAKE PART RECORD part_inventory = scs_root_object.scs_object_part_inventory for part_name in _object_utils.collect_parts_on_root(scs_root_object): _inventory.add_item(part_inventory, part_name) # MAKE VARIANT RECORD variant_inventory = scs_root_object.scs_object_variant_inventory for variant_record in loaded_variants: variant_name = variant_record[0] variantparts = variant_record[1] variant = _inventory.add_item(variant_inventory, variant_name) # fore every variant create all of the part entries and mark them included properly for part in part_inventory: part = _inventory.add_item(variant.parts, part.name) if part.name in variantparts: part.include = True else: part.include = False # MAKE LOOK RECORDS # get preset container only once to speed up import process presets_container = _material_utils.get_shader_presets_container(_get_scs_globals().shader_presets_filepath) for look_i, look in enumerate(loaded_looks): look_name = look[0] look_mat_settings = look[1] # SETUP ALL THE MATERIALS, NOTE: They should be already created by PIM import. for mat_info in mats_info: mat = bpy.data.materials[mat_info[0]] if mat_info[2] in look_mat_settings: # ASSIGN IMPORTED SHADER DATA material_effect, material_attributes, material_textures, material_section = _get_shader_data(look_mat_settings[mat_info[2]]) # TRY TO FIND SUITABLE PRESET (preset_index, preset_name, preset_section) = _find_preset(presets_container, material_effect, material_textures) if preset_index: # preset name is found within presets shaders mat.scs_props.active_shader_preset_name = preset_name if preset_section: preset_effect = preset_section.get_prop_value("Effect") mat.scs_props.mat_effect_name = preset_effect if look_i == 0: # apply default shader settings _material_utils.set_shader_data_to_material(mat, preset_section, preset_effect, is_import=True) # reapply settings from material _material_utils.set_shader_data_to_material(mat, material_section, material_effect, is_import=True, override_back_data=False) lprint("I Using shader preset on material %r.", (mat.name,)) else: print('''NO "preset_section"! (Shouldn't happen!)''') else: # import shader directly from material and mark it as imported mat.scs_props.active_shader_preset_name = "<imported>" _material_utils.set_shader_data_to_material(mat, material_section, material_effect, is_import=True) lprint("I Using imported shader on material %r.", (mat.name,)) if look_i == len(loaded_looks) - 1: # delete not needed data on material if "scs_tex_aliases" in mat: del mat["scs_tex_aliases"] # CREATE NEW LOOK ENTRY ON ROOT bpy.ops.object.add_scs_look(look_name=look_name, instant_apply=False) # apply first look after everything is done scs_root_object.scs_props.active_scs_look = 0 # fix scs root children objects count so it won't trigger persistent cycle scs_root_object.scs_cached_num_children = len(scs_root_object.children) return scs_root_object
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 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]) # 4. finally set preset to material again, which will update nodes and possible input interface changes for mat in bpy.data.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) return {'FINISHED'}
def load(filepath, pim_mats_info): """Enty point for importing PIT file :param filepath: filepath of PIT file :type filepath: str :param pim_mats_info: list of material info, one material info consists of list: [ blend_mat_name, mat_effect, original_mat_alias ] :type pim_mats_info: list of list """ print("\n************************************") print("** SCS PIT Importer **") print("** (c)2014 SCS Software **") print("************************************\n") ind = ' ' pit_container = _pix_container.get_data_from_file(filepath, ind) # TEST PRINTOUTS # ind = ' ' # for section in pit_container: # print('SEC.: "%s"' % section.type) # for prop in section.props: # print('%sProp: %s' % (ind, prop)) # for data in section.data: # print('%sdata: %s' % (ind, data)) # for sec in section.sections: # print_section(sec, ind) # print('\nTEST - Source: "%s"' % pit_container[0].props[1][1]) # print('') # TEST EXPORT # path, file = os.path.splitext(filepath) # export_filepath = str(path + '_reex' + file) # result = pix_write.write_data(pit_container, export_filepath, ind, dump_level) # if result == {'FINISHED'}: # Print(dump_level, '\nI Test export succesful! The new file:\n "%s"', export_filepath) # else: # Print(dump_level, '\nE Test export failed! File:\n "%s"', export_filepath) # LOAD HEADER ''' NOTE: skipped for now as no data needs to be readed (format_version, source, f_type, f_name, source_filename, author) = _get_header(pit_container, dump_level) ''' # LOAD GLOBALS ''' NOTE: skipped for now as no data needs to be readed (look_count, variant_count, part_count, material_count) = _get_global(pit_container, dump_level) ''' # LOAD LOOKS AND VARIANTS loaded_looks = {} looks = [] loaded_variants = [] for section in pit_container: if section.type == 'Look': look_name, look_mat_settings = _get_look(section) loaded_looks[look_name] = look_mat_settings looks.append(look_name) elif section.type == 'Variant': variant_name, variantparts = _get_variant(section) variant_record = (variant_name, variantparts) # variant_record = (getVariant(section)) loaded_variants.append(variant_record) # loaded_variants.append((getVariant(section))) # PICK ONE LOOK DATA BLOCK, NOTE: This is temporal now as we don't have proper support for Looks. if "Default" in loaded_looks: look_name = "Default" else: look_name = looks[0] # print(" look_name: %r" % look_name) look_mat_settings = loaded_looks[look_name] # SETUP ALL THE MATERIALS, NOTE: They should be already created by PIM import. for mat_info in pim_mats_info: mat = bpy.data.materials[mat_info[0]] if mat_info[2] in look_mat_settings: # ASSIGN IMPORTED SHADER DATA material_effect, material_attributes, material_textures, material_section = _get_shader_data(look_mat_settings[mat_info[2]]) # TRY TO FIND SUITABLE PRESET (preset_index, preset_name) = _find_preset(material_effect) if preset_index: # preset name is found within presets shaders mat.scs_props.active_shader_preset_name = preset_name preset_section = _material_utils.get_shader_preset(_get_scs_globals().shader_presets_filepath, preset_name) if preset_section: preset_effect = preset_section.get_prop_value("Effect") mat.scs_props.mat_effect_name = preset_effect # apply default shader settings _material_utils.set_shader_data_to_material(mat, preset_section, preset_effect, is_import=True) # reapply settings from material _material_utils.set_shader_data_to_material(mat, material_section, material_effect, is_import=True, override_back_data=False) lprint("I Using shader preset on material %r.", (mat.name,)) else: print('''NO "preset_section"! (Shouldn't happen!)''') else: # import shader directly from material and mark it as imported mat.scs_props.active_shader_preset_name = "<imported>" _material_utils.set_shader_data_to_material(mat, material_section, material_effect, is_import=True) lprint("I Using imported shader on material %r.", (mat.name,)) # delete not needed data on material if "scs_tex_aliases" in mat: del mat["scs_tex_aliases"] print("************************************") return {'FINISHED'}, loaded_variants
def _create_scs_root_object(name, loaded_variants, loaded_looks, mats_info, objects, skinned_objects, locators, armature): """Creates an 'SCS Root Object' (Empty Object) for currently imported 'SCS Game Object' and parent all import content to it. :param name: :type name: str :param loaded_variants: X :type loaded_variants: list :param loaded_looks: X :type loaded_looks: list :param mats_info: list of material info, one material info consists of list: [ blend_mat_name, mat_effect, original_mat_alias ] :type mats_info: list of list :param objects: X :type objects: list :param skinned_objects: X :type skinned_objects: list :param locators: X :type locators: list :param armature: Armature Object :type armature: bpy.types.Object :return: SCS Root Object :rtype: bpy.types.Object """ context = bpy.context # MAKE THE 'SCS ROOT OBJECT' NAME UNIQUE name = _name_utils.get_unique(name, bpy.data.objects) # CREATE EMPTY OBJECT bpy.ops.object.empty_add( view_align=False, location=(0.0, 0.0, 0.0), # rotation=rot, ) # , layers=(False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, # False, False)) # MAKE A PROPER SETTINGS TO THE 'SCS Game Object' OBJECT scs_root_object = context.active_object scs_root_object.name = name scs_root_object.scs_props.scs_root_object_export_enabled = True scs_root_object.scs_props.empty_object_type = 'SCS_Root' # print('LOD.pos: %s' % str(scs_root_object.location)) # print('CUR.pos: %s' % str(context.space_data.cursor_location)) # PARENTING if armature: # if armature is present we can specify our game object as animated scs_root_object.scs_props.scs_root_animated = "anim" # print('ARM.pos: %s' % str(armature.location)) bpy.ops.object.select_all(action='DESELECT') armature.select = True bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) armature.scs_props.parent_identity = scs_root_object.name for obj in objects: if obj not in skinned_objects: # print('OBJ.pos: %s' % str(object.location)) bpy.ops.object.select_all(action='DESELECT') obj.select = True bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) obj.scs_props.parent_identity = scs_root_object.name for obj in locators: bpy.ops.object.select_all(action='DESELECT') obj.select = True bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) obj.scs_props.parent_identity = scs_root_object.name # LOCATION scs_root_object.location = context.scene.cursor_location # MAKE ONLY 'SCS GAME OBJECT' SELECTED bpy.ops.object.select_all(action='DESELECT') for obj in bpy.data.objects: obj.select = False scs_root_object.select = True context.scene.objects.active = scs_root_object # MAKE PART RECORD part_inventory = scs_root_object.scs_object_part_inventory for part_name in _object_utils.collect_parts_on_root(scs_root_object): _inventory.add_item(part_inventory, part_name) # MAKE VARIANT RECORD variant_inventory = scs_root_object.scs_object_variant_inventory for variant_record in loaded_variants: variant_name = variant_record[0] variantparts = variant_record[1] variant = _inventory.add_item(variant_inventory, variant_name) # fore every variant create all of the part entries and mark them included properly for part in part_inventory: part = _inventory.add_item(variant.parts, part.name) if part.name in variantparts: part.include = True else: part.include = False # MAKE LOOK RECORDS # get preset container only once to speed up import process presets_container = _material_utils.get_shader_presets_container( _get_scs_globals().shader_presets_filepath) for look_i, look in enumerate(loaded_looks): look_name = look[0] look_mat_settings = look[1] # SETUP ALL THE MATERIALS, NOTE: They should be already created by PIM import. for mat_info in mats_info: mat = bpy.data.materials[mat_info[0]] if mat_info[2] in look_mat_settings: # ASSIGN IMPORTED SHADER DATA material_effect, material_attributes, material_textures, material_section = _get_shader_data( look_mat_settings[mat_info[2]]) # TRY TO FIND SUITABLE PRESET (preset_index, preset_name, preset_section) = _find_preset(presets_container, material_effect, material_textures) if preset_index: # preset name is found within presets shaders mat.scs_props.active_shader_preset_name = preset_name if preset_section: preset_effect = preset_section.get_prop_value("Effect") mat.scs_props.mat_effect_name = preset_effect if look_i == 0: # apply default shader settings _material_utils.set_shader_data_to_material( mat, preset_section, preset_effect, is_import=True) # reapply settings from material _material_utils.set_shader_data_to_material( mat, material_section, material_effect, is_import=True, override_back_data=False) lprint("I Using shader preset on material %r.", (mat.name, )) else: print('''NO "preset_section"! (Shouldn't happen!)''') else: # import shader directly from material and mark it as imported mat.scs_props.active_shader_preset_name = "<imported>" _material_utils.set_shader_data_to_material( mat, material_section, material_effect, is_import=True) lprint("I Using imported shader on material %r.", (mat.name, )) if look_i == len(loaded_looks) - 1: # delete not needed data on material if "scs_tex_aliases" in mat: del mat["scs_tex_aliases"] # CREATE NEW LOOK ENTRY ON ROOT bpy.ops.object.add_scs_look(look_name=look_name, instant_apply=False) # apply first look after everything is done scs_root_object.scs_props.active_scs_look = 0 # fix scs root children objects count so it won't trigger persistent cycle scs_root_object.scs_cached_num_children = len(scs_root_object.children) return scs_root_object