Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
        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'}
Ejemplo n.º 3
0
        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'}
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
        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'}
Ejemplo n.º 7
0
        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'}
Ejemplo n.º 8
0
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
Ejemplo n.º 9
0
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
Ejemplo n.º 10
0
        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'}
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
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