Ejemplo n.º 1
0
def create_locator_empty(name, loc, rot=(0, 0, 0), scale=(1, 1, 1), size=1.0, data_type='Prefab', hookup=None, blend_coords=False):
    """
    Creates an empty object for a Locator.
    :param name:
    :param loc:
    :param rot:
    :param scale:
    :param size:
    :param data_type:
    :param hookup:
    :param blend_coords:
    :return:
    """
    rot_quaternion = None
    if len(rot) == 4:
        rot_quaternion = rot
        rot = (0, 0, 0)

    if blend_coords:
        location = loc
    else:
        location = _convert.change_to_scs_xyz_coordinates(loc, _get_scs_globals().import_scale)

    unique_name = _name.get_unique(name, bpy.data.objects, sep=".")
    locator = bpy.data.objects.new(unique_name, None)
    locator.empty_display_type = 'PLAIN_AXES'
    locator.scs_props.object_identity = locator.name

    # link to active layer and scene and make it active and selected
    bpy.context.view_layer.active_layer_collection.collection.objects.link(locator)
    bpy.context.view_layer.objects.active = locator
    locator.select_set(True)

    # fix scene objects count to avoid callback of new object
    bpy.context.scene.scs_cached_num_objects = len(bpy.context.scene.objects)

    locator.location = location

    if rot_quaternion:
        locator.rotation_mode = 'QUATERNION'
        if blend_coords:
            locator.rotation_quaternion = rot_quaternion
        else:
            locator.rotation_quaternion = _convert.change_to_blender_quaternion_coordinates(rot_quaternion)
    else:
        locator.rotation_mode = 'XYZ'
        locator.rotation_euler = rot

    locator.scale = scale
    locator.scs_props.empty_object_type = 'Locator'
    locator.scs_props.locator_type = data_type

    if data_type == "Prefab":
        locator.scs_props.scs_part = ""

    if hookup:
        locator.scs_props.locator_model_hookup = hookup

    return locator
Ejemplo n.º 2
0
def add_animation_to_root(scs_root_object, animation_name):
    animation_inventory = scs_root_object.scs_object_animation_inventory

    # ENSURE, THAT THE NAME IS UNIQUE
    animation_name = _name.get_unique(animation_name, animation_inventory)

    # ADD THE ANIMATION
    animation = animation_inventory.add()
    animation.name = animation_name
    return animation
Ejemplo n.º 3
0
def create_locator_empty(name,
                         loc,
                         rot=(0, 0, 0),
                         scale=(1, 1, 1),
                         size=1.0,
                         data_type='Prefab',
                         hookup=None):
    """
    Creates an empty object for a Locator.
    :param name:
    :param loc:
    :param rot:
    :param scale:
    :param size:
    :param data_type:
    :param hookup:
    :return:
    """
    rot_quaternion = None
    if len(rot) == 4:
        rot_quaternion = rot
        rot = (0, 0, 0)

    bpy.ops.object.empty_add(
        type='PLAIN_AXES',
        view_align=False,
        location=_convert.change_to_scs_xyz_coordinates(
            loc,
            _get_scs_globals().import_scale),
        rotation=rot,
    )

    bpy.context.active_object.name = _name.get_unique(name,
                                                      bpy.data.objects,
                                                      sep=".")
    locator = bpy.context.active_object
    locator.scs_props.object_identity = locator.name

    if rot_quaternion:
        locator.rotation_mode = 'QUATERNION'
        locator.rotation_quaternion = _convert.change_to_blender_quaternion_coordinates(
            rot_quaternion)

    locator.scale = scale
    locator.scs_props.empty_object_type = 'Locator'
    locator.scs_props.locator_type = data_type

    if data_type == "Prefab":
        locator.scs_props.scs_part = ""

    if hookup:
        locator.scs_props.locator_model_hookup = hookup

    return locator
Ejemplo n.º 4
0
def add_animation_to_root(scs_root_object, animation_name="Default"):
    animation_inventory = scs_root_object.scs_object_animation_inventory

    # ENSURE, THAT THE NAME IS UNIQUE
    while animation_name in animation_inventory:
        animation_name = _name.get_unique(animation_name)

    # ADD THE ANIMATION
    lprint('I Adding a Animation name: "%s"', animation_name)
    animation = animation_inventory.add()
    animation.name = animation_name
    animation.active = True
    return animation
Ejemplo n.º 5
0
def add_animation_to_root(scs_root_object, animation_name="Default"):
    animation_inventory = scs_root_object.scs_object_animation_inventory

    # ENSURE, THAT THE NAME IS UNIQUE
    while animation_name in animation_inventory:
        animation_name = _name.get_unique(animation_name)

    # ADD THE ANIMATION
    lprint('I Adding a Animation name: "%s"', animation_name)
    animation = animation_inventory.add()
    animation.name = animation_name
    animation.active = True
    return animation
Ejemplo n.º 6
0
def create_locator_empty(name, loc, rot=(0, 0, 0), scale=(1, 1, 1), size=1.0, data_type="Prefab", hookup=None):
    """
    Creates an empty object for a Locator.
    :param name:
    :param loc:
    :param rot:
    :param scale:
    :param size:
    :param data_type:
    :param hookup:
    :return:
    """
    rot_quaternion = None
    if len(rot) == 4:
        rot_quaternion = rot
        rot = (0, 0, 0)

    bpy.ops.object.empty_add(
        type="PLAIN_AXES",
        view_align=False,
        location=_convert.change_to_scs_xyz_coordinates(loc, _get_scs_globals().import_scale),
        rotation=rot,
    )

    bpy.context.active_object.name = _name.get_unique(name, bpy.data.objects, sep=".")
    locator = bpy.context.active_object
    locator.scs_props.object_identity = locator.name

    if rot_quaternion:
        locator.rotation_mode = "QUATERNION"
        locator.rotation_quaternion = _convert.change_to_blender_quaternion_coordinates(rot_quaternion)

    locator.scale = scale
    locator.scs_props.empty_object_type = "Locator"
    locator.scs_props.locator_type = data_type

    if data_type == "Prefab":
        locator.scs_props.scs_part = ""

    if hookup:
        locator.scs_props.locator_model_hookup = hookup

    return locator
Ejemplo n.º 7
0
def make_scs_root_object(context, dialog=False):
    # FAIRLY SMART SELECTION OF SCS GAME OBJECT CONTENT
    scs_game_object_content = []
    for obj in context.selected_objects:
        if not obj.parent:
            scs_game_object_content.append(obj)
        else:
            if not obj.parent.select:
                scs_game_object_content.append(obj)

    # ADD SCS ROOT OBJECT (EMPTY OBJECT)
    bpy.ops.object.empty_add(
        view_align=False,
        location=context.scene.cursor_location,
    )

    # SET PROPERTIES

    name = _name.get_unique("game_object", bpy.data.objects)
    bpy.context.active_object.name = name
    new_scs_root = bpy.data.objects.get(name)
    new_scs_root.scs_props.scs_root_object_export_enabled = True
    new_scs_root.scs_props.empty_object_type = 'SCS_Root'

    # SET A NEW NAME DIALOG
    if dialog:
        bpy.ops.object.add_scs_root_object_dialog_operator('INVOKE_DEFAULT')

    # PARENT OBJECTS TO SCS ROOT OBJECT
    part_inventory = new_scs_root.scs_object_part_inventory
    if len(scs_game_object_content) > 0:

        bpy.ops.object.select_all(action='DESELECT')

        new_scs_root_mats = []
        # select content object for parenting later
        for obj in scs_game_object_content:
            obj.select = True

            # fix old parent with new children number and cleaned looks
            if obj.parent:
                ex_parent_obj = obj.parent
                obj.parent = None

                ex_parent_obj.scs_cached_num_children = len(
                    ex_parent_obj.children)

                ex_parent_scs_root = get_scs_root(ex_parent_obj)
                if ex_parent_scs_root:
                    _looks.clean_unused(ex_parent_scs_root)

            obj.scs_props.parent_identity = new_scs_root.name
            obj.scs_cached_num_children = len(obj.children)

            for slot in obj.material_slots:
                if slot.material and slot.material not in new_scs_root_mats:
                    new_scs_root_mats.append(slot.material)

        _looks.add_materials(new_scs_root, new_scs_root_mats)

        bpy.ops.object.parent_set(type='OBJECT', keep_transform=False)
        bpy.ops.object.select_all(action='DESELECT')
        new_scs_root.select = True

        # fix children count to prevent persistent to hook up
        new_scs_root.scs_cached_num_children = len(new_scs_root.children)

        for part_name in collect_parts_on_root(new_scs_root):
            _inventory.add_item(part_inventory, part_name)

    # MAKE DEFAULT PART IF THERE IS NO PARTS
    if len(part_inventory) == 0:
        _inventory.add_item(part_inventory, _PART_consts.default_name)

    return new_scs_root
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 & 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.º 9
0
def make_scs_root_object(context, dialog=False):
    # FAIRLY SMART SELECTION OF SCS GAME OBJECT CONTENT
    scs_game_object_content = []
    for obj in context.selected_objects:
        if not obj.parent:
            scs_game_object_content.append(obj)
        else:
            if not obj.parent.select:
                scs_game_object_content.append(obj)

    # ADD SCS ROOT OBJECT (EMPTY OBJECT)
    bpy.ops.object.empty_add(view_align=False, location=context.scene.cursor_location)

    # SET PROPERTIES

    name = _name.get_unique("game_object", bpy.data.objects)
    bpy.context.active_object.name = name
    new_scs_root = bpy.data.objects.get(name)
    new_scs_root.scs_props.scs_root_object_export_enabled = True
    new_scs_root.scs_props.empty_object_type = "SCS_Root"

    # SET A NEW NAME DIALOG
    if dialog:
        bpy.ops.object.add_scs_root_object_dialog_operator("INVOKE_DEFAULT")

    # PARENT OBJECTS TO SCS ROOT OBJECT
    part_inventory = new_scs_root.scs_object_part_inventory
    if len(scs_game_object_content) > 0:

        bpy.ops.object.select_all(action="DESELECT")

        new_scs_root_mats = []
        # select content object for parenting later
        for obj in scs_game_object_content:
            obj.select = True

            # fix old parent with new children number and cleaned looks
            if obj.parent:
                ex_parent_obj = obj.parent
                obj.parent = None

                ex_parent_obj.scs_cached_num_children = len(ex_parent_obj.children)

                ex_parent_scs_root = get_scs_root(ex_parent_obj)
                if ex_parent_scs_root:
                    _looks.clean_unused(ex_parent_scs_root)

            obj.scs_props.parent_identity = new_scs_root.name
            obj.scs_cached_num_children = len(obj.children)

            for slot in obj.material_slots:
                if slot.material and slot.material not in new_scs_root_mats:
                    new_scs_root_mats.append(slot.material)

        _looks.add_materials(new_scs_root, new_scs_root_mats)

        bpy.ops.object.parent_set(type="OBJECT", keep_transform=False)
        bpy.ops.object.select_all(action="DESELECT")
        new_scs_root.select = True

        # fix children count to prevent persistent to hook up
        new_scs_root.scs_cached_num_children = len(new_scs_root.children)

        for part_name in collect_parts_on_root(new_scs_root):
            _inventory.add_item(part_inventory, part_name)

    # MAKE DEFAULT PART IF THERE IS NO PARTS
    if len(part_inventory) == 0:
        _inventory.add_item(part_inventory, _PART_consts.default_name)

    return new_scs_root
Ejemplo n.º 10
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.º 11
0
def load(filepath, terrain_points_trans):
    """Loads given PIP file.

    :param filepath: complete filepath to PIP file
    :type filepath: str
    :param terrain_points_trans: terrain points transitional structure where terrain points shall be saved
    :type terrain_points_trans: io_scs_tools.imp.transition_structs.terrain_points.TerrainPntsTrans
    :return: set of operator result and list of created locators
    :rtype: tuple[set, list[bpy.types.Objects]]
    """
    scs_globals = _get_scs_globals()

    print("\n************************************")
    print("**      SCS PIP Importer          **")
    print("**      (c)2014 SCS Software      **")
    print("************************************\n")

    # from bpy_extras.image_utils import load_image  # UNUSED

    # scene = context.scene
    ind = '    '
    pip_container = _pix_container.get_data_from_file(filepath, ind)

    # 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(pip_container)
    '''

    # LOAD GLOBALS
    '''
    NOTE: skipped for now as no data needs to be readed
    (node_count,
     terrain_point_count,
     nav_curve_count,
     sign_count,
     spawn_point_count,
     traffic_light_count,
     map_point_count,
     trigger_point_count,
     intersection_count) = _get_global(pip_container)
    '''

    # DATA BUILDING
    nodes_data = {}
    # terrain_points_data = {}
    signs_data = {}
    spawn_points_data = {}
    traffic_lights_data = {}
    nav_curves_data = {}
    map_points_data = []
    trigger_points_data = []

    locators = []

    # node_index = 0
    sign_index = 0
    spawn_index = 0
    tsem_index = 0
    map_index = 0
    trp_index = 0

    for section in pip_container:
        if section.type == 'Node':
            (
                node_name,
                node_index,
                node_position,
                node_direction,
                node_input_lanes,
                node_output_lanes,
                tp_positions,
                tp_normals,
                tp_variants,
            ) = _get_node_properties(section)

            if node_name is None:
                node_name = str('Node_Locator_' + str(node_index))
            else:
                node_name = _name_utils.get_unique(node_name,
                                                   nodes_data.keys())

            node_direction = _curve_utils.set_direction(node_direction)

            nodes_data[node_name] = (node_index, node_position, node_direction,
                                     node_input_lanes, node_output_lanes,
                                     tp_positions, tp_normals, tp_variants)
        elif section.type == 'Sign':
            (sign_name, sign_position, sign_rotation, sign_model,
             sign_part) = _get_sign_properties(section)

            if sign_name is None:
                sign_name = str('Sign_Locator_' + str(sign_index))
            else:
                sign_name = _name_utils.get_unique(sign_name,
                                                   signs_data.keys())

            signs_data[sign_name] = (
                sign_index,
                sign_position,
                sign_rotation,
                sign_model,
                sign_part,
            )
            sign_index += 1
        elif section.type == 'SpawnPoint':
            (spawn_name, spawn_position, spawn_rotation,
             spawn_type) = _get_spawn_properties(section)

            if spawn_name is None:
                spawn_name = str('Sign_Locator_' + str(spawn_index))
            else:
                spawn_name = _name_utils.get_unique(spawn_name,
                                                    spawn_points_data.keys())

            spawn_points_data[spawn_name] = (
                spawn_index,
                spawn_position,
                spawn_rotation,
                spawn_type,
            )
            spawn_index += 1
        elif section.type == 'Semaphore':  # former "TrafficLight"
            (tsem_name, tsem_position, tsem_rotation, tsem_type, tsem_id,
             tsem_intervals, tsem_cycle,
             tsem_profile) = _get_t_light_properties(section)

            if tsem_name is None:
                tsem_name = str('Semaphore_Locator_' + str(tsem_index))
            else:
                tsem_name = _name_utils.get_unique(tsem_name,
                                                   traffic_lights_data.keys())

            if tsem_id is None:
                tsem_id = -1

            traffic_lights_data[tsem_name] = (
                tsem_position,
                tsem_rotation,
                tsem_type,
                tsem_id,
                tsem_intervals,
                tsem_cycle,
                tsem_profile,
            )
            tsem_index += 1
        elif section.type == 'Curve':
            (cur_name, cur_index, cur_flags, cur_leads_to_nodes,
             cur_traffic_rule, cur_sempahore_id, cur_next_curves,
             cur_prev_curves, cur_length, bezier_start_pos, bezier_start_dir,
             bezier_start_qua, bezier_end_pos, bezier_end_dir,
             bezier_end_qua) = _get_curve_properties(section)

            nav_curves_data[cur_index] = (
                cur_name,
                cur_flags,
                cur_leads_to_nodes,  # not used
                cur_traffic_rule,
                cur_sempahore_id,
                cur_next_curves,
                cur_prev_curves,
                cur_length,  # not used
                bezier_start_pos,
                bezier_start_dir,
                bezier_start_qua,
                bezier_end_pos,
                bezier_end_dir,
                bezier_end_qua,
            )
        elif section.type == 'MapPoint':
            (map_indexx, map_name, map_visual_flags, map_nav_flags,
             map_position, map_neighbours) = _get_map_point_properties(section)

            if map_indexx is None:
                map_indexx = map_index

            if map_name is None:
                map_name = str("Map_Point_Locator_" + str(map_indexx))

            map_points_data.append((
                map_name,
                map_indexx,
                map_visual_flags,
                map_nav_flags,
                map_position,
                map_neighbours,
            ))
            map_index += 1
        elif section.type == 'TriggerPoint':
            (trp_indexx, trp_name, trp_trigger_id, trp_action, trp_range,
             trp_reset_delay, trp_flags, trp_position,
             trp_neighbours) = _get_trigger_point_properties(section)

            if trp_indexx is None:
                trp_indexx = trp_index

            if trp_name is None:
                trp_name = str('Trigger_Locator_' + str(trp_indexx))

            trp_range = float(trp_range)

            trigger_points_data.append((
                trp_name,
                trp_indexx,
                trp_action,
                trp_range,
                trp_reset_delay,
                trp_flags,
                trp_position,
                trp_neighbours,
            ))
            trp_index += 1

            # print('')

    # CREATE NODES
    for name in nodes_data:
        loc = _create_node_locator(
            name,
            nodes_data[name][0],  # node_index
            nodes_data[name][1],  # node_position
            nodes_data[name][2],  # node_direction
        )

        tp_pos_l = nodes_data[name][5]
        tp_nor_l = nodes_data[name][6]
        tp_var_l = nodes_data[name][7]

        # save terrain points into transitional structure
        if len(tp_var_l) > 0:  # save per variant block

            for var_i, var in enumerate(tp_var_l):
                for i in range(var[0], var[0] + var[1]):
                    terrain_points_trans.add(var_i, nodes_data[name][0],
                                             tp_pos_l[i], tp_nor_l[i])

        else:

            for i in range(len(tp_pos_l)):
                terrain_points_trans.add(-1, nodes_data[name][0], tp_pos_l[i],
                                         tp_nor_l[i])

        if loc:
            _print_locator_result(loc, "Node", name)
            locators.append(loc)

    # CREATE SIGNS
    for name in signs_data:
        # print('signs_data[name]: %s' % str(signs_data[name]))
        loc = _create_sign_locator(name, signs_data[name][1],
                                   signs_data[name][2], signs_data[name][3],
                                   signs_data[name][4],
                                   scs_globals.scs_sign_model_inventory)
        if loc:
            _print_locator_result(loc, "Sign", name)
            locators.append(loc)

    # CREATE SPAWN POINTS
    for name in spawn_points_data:
        # print('spawn_points_data[name]: %s' % str(spawn_points_data[name]))
        loc = _create_spawn_locator(
            name,
            spawn_points_data[name][1],
            spawn_points_data[name][2],
            spawn_points_data[name][3],
        )
        if loc:
            _print_locator_result(loc, "Spawn Point", name)
            locators.append(loc)

    # CREATE TRAFFIC LIGHTS
    for name in traffic_lights_data:
        # print('traffic_lights_data[name]: %s' % str(traffic_lights_data[name]))
        loc = _create_traffic_light_locator(
            name,
            traffic_lights_data[name][0],  # tsem_position
            traffic_lights_data[name][1],  # tsem_rotation
            traffic_lights_data[name][2],  # tsem_type
            traffic_lights_data[name][3],  # tsem_id
            traffic_lights_data[name][4],  # tsem_intervals
            traffic_lights_data[name][5],  # tsem_cycle
            traffic_lights_data[name][6],  # tsem_profile
            scs_globals.scs_tsem_profile_inventory)
        if loc:
            _print_locator_result(loc, "Traffic Semaphore", name)
            locators.append(loc)

    # PREPROCESS CURVE DATA AND CREATE LOCATORS AND DICTIONARY OF CONNECTIONS
    conns_dict = {}
    nav_locs_count = 0
    for index in nav_curves_data:

        # assemble variables
        # cur_name = nav_curves_data[index][0]
        cur_flags = nav_curves_data[index][1]
        cur_traffic_rule = nav_curves_data[index][3]
        cur_sempahore_id = nav_curves_data[index][4]
        cur_next_curves = nav_curves_data[index][5]
        cur_prev_curves = nav_curves_data[index][6]

        bezier_start_pos = nav_curves_data[index][8]
        bezier_start_dir = bezier_start_qua = bezier_end_dir = bezier_end_qua = None
        if nav_curves_data[index][9]:
            bezier_start_dir = _curve_utils.set_direction(
                nav_curves_data[index][9])
        else:
            bezier_start_qua = nav_curves_data[index][10]

        bezier_end_pos = nav_curves_data[index][11]
        if nav_curves_data[index][12]:
            bezier_end_dir = _curve_utils.set_direction(
                nav_curves_data[index][12])
        else:
            bezier_end_qua = nav_curves_data[index][13]

        # check if there is need to create new one or alter the existing
        curve_locators_to_create = {"start": True, "end": True}
        for prev_curve_ind in cur_prev_curves:

            if prev_curve_ind != -1 and prev_curve_ind in conns_dict:

                if "end" in conns_dict[prev_curve_ind]:
                    curve_locators_to_create["start"] = False

                    # properly create entry for current curve
                    if index in conns_dict:
                        conns_dict[index]["start"] = conns_dict[
                            prev_curve_ind]["end"]
                    else:
                        conns_dict[index] = {
                            "start": conns_dict[prev_curve_ind]["end"]
                        }

                    break

        for next_curve_ind in cur_next_curves:

            if next_curve_ind != -1 and next_curve_ind in conns_dict:

                if "start" in conns_dict[next_curve_ind]:
                    curve_locators_to_create["end"] = False

                    if index in conns_dict:
                        conns_dict[index]["end"] = conns_dict[next_curve_ind][
                            "start"]
                    else:
                        conns_dict[index] = {
                            "end": conns_dict[next_curve_ind]["start"]
                        }

                    break

        # CREATE 2 LOCATORS FOR EACH CURVE IF NEEDED
        for loc_key in curve_locators_to_create:

            nav_locator_data = {}

            nav_locs_count += 1
            if loc_key == "start":

                nav_locator_data['np_name'] = "Nav_Point_" + str(
                    nav_locs_count)
                nav_locator_data['np_pos'] = bezier_start_pos
                nav_locator_data['np_dir'] = bezier_start_dir
                nav_locator_data['np_qua'] = bezier_start_qua

            elif loc_key == "end":

                nav_locator_data['np_name'] = "Nav_Point_" + str(
                    nav_locs_count)
                nav_locator_data['np_pos'] = bezier_end_pos
                nav_locator_data['np_dir'] = bezier_end_dir
                nav_locator_data['np_qua'] = bezier_end_qua

            nav_locator_data['np_low_probab'] = (
                cur_flags & _PL_consts.PNCF.LOW_PROBABILITY) != 0
            nav_locator_data['np_add_priority'] = (
                cur_flags & _PL_consts.PNCF.ADDITIVE_PRIORITY) != 0
            nav_locator_data['np_limit_displace'] = (
                cur_flags & _PL_consts.PNCF.LIMIT_DISPLACEMENT) != 0

            nav_locator_data[
                'np_allowed_veh'] = cur_flags & _PL_consts.PNCF.ALLOWED_VEHICLES_MASK

            if cur_flags & _PL_consts.PNCF.LEFT_BLINKER != 0:
                nav_locator_data['np_blinker'] = _PL_consts.PNCF.LEFT_BLINKER
            elif cur_flags & _PL_consts.PNCF.FORCE_NO_BLINKER != 0:
                nav_locator_data[
                    'np_blinker'] = _PL_consts.PNCF.FORCE_NO_BLINKER
            elif cur_flags & _PL_consts.PNCF.RIGHT_BLINKER != 0:
                nav_locator_data['np_blinker'] = _PL_consts.PNCF.RIGHT_BLINKER
            else:
                nav_locator_data['np_blinker'] = 0

            nav_locator_data['np_prior_modif'] = (
                cur_flags & _PL_consts.PNCF.PRIORITY_MASK
            ) >> _PL_consts.PNCF.PRIORITY_SHIFT

            nav_locator_data['np_semaphore_id'] = cur_sempahore_id
            nav_locator_data['np_traffic_rule'] = cur_traffic_rule

            for node_data in nodes_data.values():

                if loc_key == "start":

                    for lane_index, curve_index in enumerate(node_data[3]):

                        if curve_index == index:

                            nav_locator_data['np_boundary'] = 1 + lane_index
                            nav_locator_data['np_boundary_node'] = node_data[0]
                            break

                else:

                    for lane_index, curve_index in enumerate(node_data[4]):

                        if curve_index == index:

                            nav_locator_data[
                                'np_boundary'] = 1 + lane_index + _PL_consts.PREFAB_LANE_COUNT_MAX
                            nav_locator_data['np_boundary_node'] = node_data[0]
                            break

            # locator already exists just set properties
            if curve_locators_to_create[loc_key] is False:

                loc_obj = conns_dict[index][loc_key]
                _set_nav_locator_props(loc_obj, nav_locator_data,
                                       loc_key == "start")

                continue

            loc = _create_nav_locator(nav_locator_data)
            _set_nav_locator_props(loc, nav_locator_data, loc_key == "start")
            locators.append(loc)
            if loc:
                # decide which side to update
                if loc_key == "start":
                    related_curves = cur_prev_curves
                    related_end = "end"
                else:
                    related_curves = cur_next_curves
                    related_end = "start"

                # create or update references for current connection
                if index not in conns_dict:
                    conns_dict[index] = {loc_key: loc}
                else:
                    conns_dict[index][loc_key] = loc

                # update references for prev or next connections
                for prev_curve_ind in related_curves:

                    if prev_curve_ind != -1:

                        if prev_curve_ind in conns_dict:

                            if related_end not in conns_dict[prev_curve_ind]:
                                conns_dict[prev_curve_ind][related_end] = loc

                        else:

                            conns_dict[prev_curve_ind] = {related_end: loc}

    # CREATE CONNECTIONS BETWEEN NAVIGATION POINTS
    for connection in conns_dict.values():
        _group_connections_wrapper.create_connection(connection["start"],
                                                     connection["end"])

    # COLLECT MAP POINT CONNECTIONS
    connections = []
    for map_point in map_points_data:

        # ignore auto generated map points
        if map_point[3] & _PL_consts.MPNF.NAV_BASE != 0:
            continue

        loc_index = map_point[1]

        for loc_neighbour_index in map_point[5]:

            if loc_neighbour_index == -1:
                continue

            if loc_index == loc_neighbour_index:
                continue

            for con in connections:
                if loc_neighbour_index == con[0] and loc_index == con[1]:
                    continue

                if loc_neighbour_index == con[1] and loc_index == con[0]:
                    continue

            connections.append((loc_index, loc_neighbour_index))

    # CREATE MAP POINTS
    mp_locs = {}
    for map_point in map_points_data:
        name = map_point[0]

        # ignore auto generated map points
        if map_point[3] & _PL_consts.MPNF.NAV_BASE != 0:
            continue

        loc = _create_map_locator(
            map_point[0],
            map_point[2],
            map_point[3],
            map_point[4],
        )

        _print_locator_result(loc, "Map Point", name)

        if loc:
            locators.append(loc)
            mp_locs[map_point[1]] = loc

    # APPLY MAP POINT CONNECTIONS
    for connection in connections:

        # safety check if connection indexes really exists
        if connection[0] in mp_locs and connection[1] in mp_locs:
            start_node = mp_locs[connection[0]]
            end_node = mp_locs[connection[1]]
        else:
            lprint('E Map connection out of range: %s', (str(connection), ))
            continue

        _group_connections_wrapper.create_connection(start_node, end_node)

    # COLLECT TRIGGER POINT CONNECTIONS
    connections = []
    for tr_point in trigger_points_data:

        loc_index = tr_point[1]

        # print('      name: %s' % tr_point[0])
        if len(tr_point[7]) != 2:
            lprint(
                'W Unexpected number of connections (%i) for Trigger Point "%s"!',
                (len(tr_point[7]), tr_point[0]))

        for loc_neighbour_index in tr_point[7]:
            connections.append((loc_index, loc_neighbour_index))

    # CREATE TRIGGER POINTS
    tp_locs = {}
    for tr_point in trigger_points_data:
        name = tr_point[0]
        # print('trigger_points_data[%r]: %s' % (name, str(tr_point)))
        loc = _create_trigger_locator(
            tr_point[0], tr_point[2], tr_point[3], tr_point[4], tr_point[5],
            tr_point[6], scs_globals.scs_trigger_actions_inventory)

        _print_locator_result(loc, "Trigger Point", name)

        if loc:
            locators.append(loc)
            tp_locs[tr_point[1]] = loc

    for connection in connections:

        # safety check if connection indexes really exists
        if connection[0] in tp_locs and connection[1] in tp_locs:
            start_node = tp_locs[connection[0]]
            end_node = tp_locs[connection[1]]
        else:
            print('E Trigger connection: %s', (str(connection), ))
            continue

        _group_connections_wrapper.create_connection(start_node, end_node)

    print("************************************")
    return {'FINISHED'}, locators
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
Ejemplo n.º 13
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