Example #1
0
    def name_update(self, context):

        lprint("D SCS Look inventory name update: %s", (self.name, ))

        # convert name to game engine like name
        tokenized_name = _name_utils.tokenize_name(self.name)
        if self.name != tokenized_name:
            self.name = tokenized_name

        # always get scs root to have access to look inventory
        scs_root_obj = _object_utils.get_scs_root(context.active_object)

        # if there is more of variants with same name, make postfixed name (this will cause another name update)
        if len(
                _inventory.get_indices(scs_root_obj.scs_object_look_inventory,
                                       self.name)) == 2:  # duplicate

            i = 1
            new_name = _name_utils.tokenize_name(self.name + "_" +
                                                 str(i).zfill(2))
            while _inventory.get_index(scs_root_obj.scs_object_look_inventory,
                                       new_name) != -1:
                new_name = _name_utils.tokenize_name(self.name + "_" +
                                                     str(i).zfill(2))
                i += 1

            if new_name != self.name:
                self.name = new_name
Example #2
0
        def execute(self, context):
            mesh = context.active_object.data

            start_time = time()

            # prepare buffers
            vcolors_buffer_arrays = [
                numpy.array([0.0] * (len(mesh.loops) * 3)),
                numpy.array([0.0] * (len(mesh.loops) * 3)),
                numpy.array([0.0] * (len(mesh.loops) * 3)),
                numpy.array([0.0] * (len(mesh.loops) * 3))
            ]

            # rebake
            result = _mesh_utils.vcoloring_rebake(mesh, vcolors_buffer_arrays, None)
            if result:

                message = "I Successful! Vertex colors rebake took: %.4fs" % (time() - start_time)
                lprint(message)
                self.report({'INFO'}, message[2:])

                _view3d_utils.tag_redraw_all_view3d()  # trigger view update to see rebaked colors

            else:

                message = "E Failed! This shouldn't happen, please contact the developer..."
                lprint(message)
                self.report({'ERROR'}, message[2:])

            return {'FINISHED'}
Example #3
0
    def get_tobj_filepath(texture_data_value):
        # print(' texture_data_value: %r' % texture_data_value)
        if texture_data_value != '':

            # exception for Windows so os.path.join can correctly join paths
            texture_data_value = texture_data_value.replace("/", os.sep)

            base_path = _get_scs_globals().scs_project_path
            if os.path.isdir(base_path):
                # print(' base_path: %r' % base_path)
                head, tail = os.path.split(texture_data_value)
                if head.startswith(os.sep):
                    head = head[1:]
                    # print(' head: %r' % head)
                tobj_path = os.path.join(base_path, head)
                # print(' tobj_path: %r' % tobj_path)
                tobj_name = str(tail + ".tobj")
                # print(' tobj_name: %r' % tobj_name)
                tobj_path = os.path.join(tobj_path, tobj_name)
                # print(' tobj_filepath: %r' % tobj_filepath)
                if os.path.isfile(tobj_path):
                    return tobj_path
                else:
                    lprint("E Texture file %r not found!", (tobj_path,))
            else:
                lprint("E No 'base' directory!")
        return None
Example #4
0
def get_data_from_file(filepath, ind, print_info=False):
    """Returns entire data in data container from specified PIX file.

    :param filepath: File path to be read
    :type filepath: str
    :param ind: Indentation which is expected in the file
    :type ind: str
    :param print_info: Whether to print the debug printouts
    :type print_info: bool
    :return: PIX Section Object Data
    :rtype: list of SectionData
    """

    if filepath is None:
        lprint("D Aborting PIX file read, 'None' file!")
        return None

    # print('    filepath: "%s"\n' % filepath)
    container, state = _pix_parser.read_data(filepath, ind, print_info)
    if len(container) < 1:
        lprint('\nE File "%s" is empty!', (_path_utils.readable_norm(filepath),))
        return None

    # print_container(container)  # TEST PRINTOUTS
    # write_config_file(container, filepath, ind, "_reex")  # TEST REEXPORT

    return container
Example #5
0
    def __init__(self, index, position, direction):
        """Constructs Node for PIP.

        :param index: index of node in PIP file
        :type index: int
        :param position: global position of the locator in SCS coordinates
        :type position: tuple | Vector
        :param direction: absolute rotation of the locator in SCS coordinates
        :type direction: tuple | Vector
        """

        self.__index = index
        self.__position = position
        self.__direction = direction
        self.__input_lanes = [-1] * _PL_consts.PREFAB_LANE_COUNT_MAX
        self.__output_lanes = [-1] * _PL_consts.PREFAB_LANE_COUNT_MAX

        self.__terrain_point_count = 0
        self.__terrain_point_variant_count = 0

        self.__stream_count = 0
        self.__tp_streams = OrderedDict()
        """:type : dict[str, Stream]"""

        self.__tp_per_variant = {
        }  # saving terrain points per variant index, it gets converted to streams when requesting section
        """:type : dict[int,list[tuple]]"""

        Node.__global_node_counter += 1

        # report maximum node count reach point
        if Node.get_global_node_count() > _PL_consts.PREFAB_NODE_COUNT_MAX:
            lprint(
                "W More than maximum allowed number (max: %s) of Control Nodes will be exported, expect problems in game!",
                (_PL_consts.PREFAB_NODE_COUNT_MAX, ))
Example #6
0
def init(data_block):
    """Initialize property in given Blender data block. If custom property with preset name is already taken
    function will output the warning that it will be overwritten.

    :param data_block: data block where custom property should be saved (currently this should be bpy.data.groups)
    :type data_block: bpy_struct
    """

    if MAIN_DICT in data_block:
        lprint("W Custom property on datablock %s will be reset to init value and used for connections storage.", (str(data_block),))
    else:
        lprint("D Just to inform that init was invoked!")

    data_block[MAIN_DICT] = {
        CACHE: {
            LOCATORS: {},
            OBJS_COUNT: 0
        },
        REFS: {
            LOCATORS: {},
            CONNECTIONS: {
                COUNT: 1,
                ENTRIES: {}
            }
        },
        CONNS_TO_RECALC: {}
    }
Example #7
0
def _get_part(section):
    name = None
    pieces = []
    locators = []
    for prop in section.props:
        if prop[0] in ("", "#"):
            pass
        elif prop[0] == "Name":
            name = prop[1]
        elif prop[0] == "PieceCount":
            pass
        elif prop[0] == "LocatorCount":
            pass
        elif prop[0] == "Pieces":
            pieces = prop[1]
        elif prop[0] == "Locators":
            locators = prop[1]
        else:
            lprint('\nW Unknown property in "Global" data: "%s"!', prop[0])
    if not isinstance(pieces, list):
        if isinstance(pieces, int):
            pieces = [pieces]
    if not isinstance(locators, list):
        if isinstance(locators, int):
            locators = [locators]

    return name, pieces, locators
Example #8
0
def _get_locator(section):
    """Receives a Collision Locator section and returns its properties in its own variables.
    For any item that fails to be found, it returns None."""
    locator_name = locator_index = locator_position = locator_rotation = locator_alias = \
        locator_weight = locator_type = locator_parameters = locator_convex_piece = None
    for prop in section.props:
        if prop[0] in ("", "#"):
            pass
        elif prop[0] == "Name":
            locator_name = prop[1]
        elif prop[0] == "Index":
            locator_index = prop[1]
        elif prop[0] == "Position":
            locator_position = prop[1]
        elif prop[0] == "Rotation":
            locator_rotation = prop[1]
        elif prop[0] == "Alias":
            locator_alias = prop[1]
        elif prop[0] == "Weight":
            locator_weight = prop[1]
        elif prop[0] == "Type":
            locator_type = prop[1]
        elif prop[0] == "Parameters":
            locator_parameters = prop[1]
        elif prop[0] == "ConvexPiece":
            locator_convex_piece = prop[1]
        else:
            lprint('\nW Unknown property in "Locator" data: "%s"!', prop[0])
    return (locator_name, locator_index, locator_position, locator_rotation,
            locator_alias, locator_weight, locator_type, locator_parameters,
            locator_convex_piece)
Example #9
0
        def execute_export(self, context, disable_local_view):
            """Actually executes export of current selected objects (bpy.context.selected_objects)

            :param context: operator context
            :type context: bpy_struct
            :param disable_local_view: True if you want to disable local view after export
            :type disable_local_view: bool
            :return: succes of batch export
            :rtype: {'FINISHED'} | {'CANCELLED'}
            """
            _get_scs_globals().content_type = 'selection'  # NOTE: I'm not sure if this is still necessary.

            try:
                result = _export.batch_export(self, tuple(bpy.context.selected_objects), exclude_switched_off=False)
            except Exception as e:

                result = {"CANCELLED"}
                context.window.cursor_modal_restore()

                import traceback

                traceback.print_exc()
                lprint("E Unexpected %r accured during batch export, see stack trace above.",
                       (type(e).__name__,),
                       report_errors=1,
                       report_warnings=1)

            if disable_local_view:
                _view3d_utils.switch_local_view(False)

            return result
Example #10
0
        def execute(self, context):
            lprint('D Decrease Animation Steps...')
            scene = context.scene
            scene.use_preview_range = True
            action = context.active_object.animation_data.action

            if action.scs_props.anim_export_step == 1:
                lprint('E Cannot set lower value for %r than %i!', ('Export Step', 1))
            else:
                active_object = context.active_object
                scs_root_object = _object_utils.get_scs_root(active_object)
                # active_scs_animation = scs_root_object.scs_props.active_scs_animation
                inventory = scs_root_object.scs_object_animation_inventory
                # animation = inventory[active_scs_animation]

                # MOVE FRAMES
                # print_fcurve = 13
                for fcurve_i, fcurve in enumerate(action.fcurves):
                    # if fcurve_i == print_fcurve: print('fcurve: %r - %s' % (str(fcurve.data_path), str(fcurve.range())))
                    for keyframe_i, keyframe in enumerate(fcurve.keyframe_points):
                        # if fcurve_i == print_fcurve: print('  %i keyframe: %s' % (keyframe_i, str(keyframe.co)))

                        # OLD WAY OF INCREASING ACTION LENGTH FROM THE FIRST KEYFRAME
                        # start_frame = fcurve.range()[0]
                        # actual_frame = keyframe.co.x
                        # keyframe.co.x = ((actual_frame - start_frame) / 2) + start_frame

                        # NEW WAY - SIMPLE DOUBLING THE VALUES
                        keyframe.co.x /= 2
                    fcurve.update()

                    # ## PRINTOUTS
                    # print('  group: %r' % str(fcurve.group.name))
                    # for channel_i, channel in enumerate(fcurve.group.channels):
                    # print('    %i channel: %s - %s' % (channel_i, str(channel.data_path), str(channel.range())))
                    # for keyframe_i, keyframe in enumerate(channel.keyframe_points):
                    # print('      %i keyframe: %s' % (keyframe_i, str(keyframe.co)))

                # INCREASE GLOBAL RANGE
                scene.frame_start /= 2
                scene.frame_end /= 2

                # INCREASE PREVIEW RANGE
                scene.frame_preview_start /= 2
                scene.frame_preview_end /= 2

                # INCREASE END FRAME NUMBER IN ALL ANIMATIONS THAT USES THE ACTUAL ACTION
                for anim in inventory:
                    if anim.action == action.name:
                        anim.anim_start /= 2
                        anim.anim_end /= 2

                # INCREASE EXPORT STEP
                # print('anim_export_step: %s' % str(action.scs_props.anim_export_step))
                action.scs_props.anim_export_step /= 2

                # INCREASE FPS
                scene.render.fps /= 2

            return {'FINISHED'}
Example #11
0
        def execute(self, context):
            lprint('D Import Animation Action...')

            '''
            print('  o directory: %r' % str(self.directory))
            print('  o files:')
            for file in self.files:
                print('  o   file: %r' % str(file.name))
            '''

            pia_files = [os.path.join(self.directory, file.name) for file in self.files]

            if context.active_object.type == 'ARMATURE':
                armature = context.active_object
            else:
                return {'CANCELLED'}

            skeleton = None
            bones = None

            '''
            for file in pia_files:
                print('  o   file: %r' % str(file))
            '''
            root_object = _object_utils.get_scs_root(armature)

            lprint('S armature: %s\nskeleton: %s\nbones: %s\n', (str(armature), str(skeleton), str(bones)))
            _import.pia.load(root_object, pia_files, armature)  # , skeleton, bones)
            return {'FINISHED'}
Example #12
0
def _get_t_light_properties(section):
    """Receives a Traffic Semaphore section and returns its properties in its own variables.
    For any item that fails to be found, it returns None."""
    tsem_name = tsem_position = tsem_rotation = tsem_type = tsem_id = \
        tsem_intervals = tsem_cycle = tsem_profile = None
    for prop in section.props:
        if prop[0] in ("", "#"):
            pass
        elif prop[0] == "Name":
            tsem_name = prop[1]
        elif prop[0] == "Position":
            tsem_position = prop[1]
        elif prop[0] == "Rotation":
            tsem_rotation = prop[1]
        elif prop[0] == "Type":
            tsem_type = prop[1]
        elif prop[0] == "SemaphoreID":
            tsem_id = prop[1]  # former "TrafficLightID"
        elif prop[0] == "Intervals":
            tsem_intervals = prop[1]
        elif prop[0] == "Cycle":
            tsem_cycle = prop[1]
        elif prop[0] == "Profile":
            tsem_profile = prop[1]
        else:
            lprint('\nW Unknown property in "Traffic Semaphore" data: "%s"!', prop[0])
    return (tsem_name,
            tsem_position,
            tsem_rotation,
            tsem_type,
            tsem_id,
            tsem_intervals,
            tsem_cycle,
            tsem_profile)
Example #13
0
    def set_input_boundaries(self, scs_props):
        """Sets prefab entry/input lane and node index.

        :param scs_props: scs props from start prefab locator used in this curve
        :type scs_props: io_scs_tools.properties.object.ObjectSCSTools
        """

        boundary_lane = int(scs_props.locator_prefab_np_boundary)
        boundary_node = int(scs_props.locator_prefab_np_boundary_node)

        # calculate actual boundary lane index
        if boundary_lane > 0:

            if boundary_lane <= _PL_consts.PREFAB_LANE_COUNT_MAX:

                self.__tmp_start_lane_i = boundary_lane - 1

                if 0 <= boundary_node < _PL_consts.PREFAB_NODE_COUNT_MAX:

                    self.__tmp_start_node_i = boundary_node

                else:

                    lprint("D Given input node index in curve(index: %s) is invalid: %s. Ignoring it.",
                           (self.__index, boundary_node))

            else:

                lprint("D Given output lane boundary index in curve(index: %s) is invalid: %s. Ignoring it.",
                       (self.__index, boundary_lane))
Example #14
0
    def modal(self, context, event):

        # if abort was requested finish immediately
        if SCSPathsInitialization.__static_abort_instances:
            self.cancel(context)
            lprint("I Paths initialization aborted, deleting operator!")
            return {'FINISHED'}

        if event.type == "TIMER":  # process timer event

            if len(SCSPathsInitialization.__static_paths_list
                   ) <= 0:  # once no more paths to process abort it

                # NOTE: canceling has to be done in timer event.
                # Otherwise finishing operator with status 'FINISHED' eats event and
                # stops event in this operator and cancels action which user wanted to do.
                self.cancel(context)
                lprint("I Paths initialization done, deleting operator!")
                return {'FINISHED'}

            if not self.__path_in_progress:  # if not in progress then trigger execute and process next

                self.execute(context)

        return {'PASS_THROUGH'}
Example #15
0
def get_stream_rgb(mesh, output_type, dummy_alpha=False):
    """
    Takes a mesh and returns all vertex color layers existing in the mesh and requested
    number of empty containers for streams ("section_data" data type).
    :param mesh:
    :param output_type:
    :param dummy_alpha:
    :return:
    """
    if mesh.vertex_colors:
        rgb_all_layers = mesh.vertex_colors
        streams_vcolor = []
        for rgb_i in range(len(rgb_all_layers)):
            if output_type == "def1":
                if dummy_alpha:
                    streams_vcolor.append(("_RGBA" + str(rgb_i), []))
                else:
                    streams_vcolor.append(("_RGB" + str(rgb_i), []))
            else:
                if dummy_alpha:
                    streams_vcolor.append(("_RGBA", []))
                else:
                    streams_vcolor.append(("_RGB", []))
                break
                # print('rgb_layer: %s' % str(rgb_all_layers))
                # for item in rgb_all_layers:
                # print('\trgb_layer: %s' % str(item))
    else:
        rgb_all_layers = None
        streams_vcolor = None
        lprint('I NO RGB layers in "%s" mesh!' % mesh.name)
    return rgb_all_layers, streams_vcolor
Example #16
0
def get_skeleton_relative_filepath(armature, directory, default_name):
    """Get's skeleton relative path to given directory. This path can be used for linking
    skeletons in PIM and PIA files.

    :param armature: armature object which will be used as scs skeleton
    :type armature: bpy.types.Object
    :param directory: directory from which relative path of skeleton should be gotten
    :type directory: str
    :param default_name: if custom path is empty this name will be used as the name of pis file
    :type default_name: str
    :return: relative path to predicted PIS file of given armature
    :rtype: str
    """

    skeleton_custom_dir = armature.scs_props.scs_skeleton_custom_export_dirpath
    skeleton_custom_name = armature.scs_props.scs_skeleton_custom_name

    skeleton_path = ""
    if skeleton_custom_dir != "":
        if skeleton_custom_dir.startswith("//"):
            skeleton_path = os.path.relpath(os.path.join(_get_scs_globals().scs_project_path, skeleton_custom_dir[2:]), directory)
        else:
            lprint("E Custom skeleton export path is not relative to SCS Project Base Path.\n\t   " +
                   "Custom path will be ignored, which might lead to wrongly linked skeleton file inside PIM and PIA files.")

    skeleton_name = (skeleton_custom_name if skeleton_custom_name != "" else default_name) + ".pis"

    return os.path.join(skeleton_path, skeleton_name)
Example #17
0
def get_stream_uvs(mesh, active_uv_only):
    """
    Takes a mesh and returns requested number of UV layers from the mesh and
    the same number of empty containers for streams ("section_data" data type).
    :param mesh:
    :param active_uv_only:
    :return:
    """
    if mesh.uv_layers:
        streams_uv = []
        if active_uv_only:
            requested_uv_layers = (mesh.uv_layers.active,)
            streams_uv.append(("_UV0", []))
        else:
            requested_uv_layers = mesh.uv_layers
            for uv_i in range(len(requested_uv_layers)):
                streams_uv.append(("_UV" + str(uv_i), []))
                # print('uv_layer: %s' % str(requested_uv_layers))
                # for item in requested_uv_layers:
                # print('\tuv_layer: %s' % str(item))
    else:
        requested_uv_layers = None
        streams_uv = None
        lprint('I NO UV layers in "%s" mesh!' % mesh.name)
    return requested_uv_layers, streams_uv
Example #18
0
def _get_global(pic_container):
    """Receives PIC container and returns all its Global properties in its own variables.
    For any item that fails to be found, it returns None."""
    vertex_count = triangle_count = material_count = piece_count = part_count = locator_count = None
    for section in pic_container:
        if section.type == "Global":
            for prop in section.props:
                if prop[0] in ("", "#"):
                    pass
                elif prop[0] == "VertexCount":
                    vertex_count = prop[1]
                elif prop[0] == "TriangleCount":
                    triangle_count = prop[1]
                elif prop[0] == "MaterialCount":
                    material_count = prop[1]
                elif prop[0] == "PieceCount":
                    piece_count = prop[1]
                elif prop[0] == "PartCount":
                    part_count = prop[1]
                elif prop[0] == "LocatorCount":
                    locator_count = prop[1]
                else:
                    lprint('\nW Unknown property in "Global" data: "%s"!',
                           prop[0])
    return vertex_count, triangle_count, material_count, piece_count, part_count, locator_count
Example #19
0
def fix_visibility(locator):
    """Fix layers visibility and hide property for preview model on given locator

    :param locator: locator object for which preview model layers should synced
    :type locator: bpy.types.Object
    """

    prevm_id = _cache.get_entry(locator.name)

    if prevm_id:

        # make sure that preview model is uncached if doesn't exists anymore
        if prevm_id not in bpy.data.objects:
            lprint("D Fix layers from preview model will uncache %r", (prevm_id,))
            _cache.delete_entry(prevm_id)
            return

        prevm_obj = bpy.data.objects[prevm_id]

        # layers check
        if list(prevm_obj.layers) != list(locator.layers):
            prevm_obj.layers = tuple(locator.layers)

        # hide property check
        if prevm_obj.hide != locator.hide:
            prevm_obj.hide = locator.hide
Example #20
0
        def get_platform_depended_game_path():
            """Gets platform dependent game path as root directory for storing SCS games user data.

            :return: game path or empty string if OS is neither Windows, Linux or Mac OS X
            :rtype: str
            """

            game_path = ""

            if platform == "linux":  # Linux

                game_path = os.path.expanduser("~/.local/share")

            elif platform == "darwin":  # Mac OS X

                game_path = os.path.expanduser("~/Library/Application Support")

            elif platform == "win32":  # Windows

                try:
                    import winreg

                    with winreg.OpenKey(winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders") as key:

                        personal = winreg.QueryValueEx(key, "Personal")
                        game_path = str(personal[0])

                except OSError as e:
                    import traceback

                    lprint("E Error while looking for My Documents in registry: %r", type(e).__name__)
                    traceback.print_exc()

            return game_path
Example #21
0
    def __init__(self, index, position, direction):
        """Constructs Node for PIP.

        :param index: index of node in PIP file
        :type index: int
        :param position: global position of the locator in SCS coordinates
        :type position: tuple | Vector
        :param direction: absolute rotation of the locator in SCS coordinates
        :type direction: tuple | Vector
        """

        self.__index = index
        self.__position = position
        self.__direction = direction
        self.__input_lanes = [-1] * _PL_consts.PREFAB_LANE_COUNT_MAX
        self.__output_lanes = [-1] * _PL_consts.PREFAB_LANE_COUNT_MAX

        self.__terrain_point_count = 0
        self.__terrain_point_variant_count = 0

        self.__stream_count = 0
        self.__tp_streams = OrderedDict()
        """:type : dict[str, Stream]"""

        self.__tp_per_variant = {}  # saving terrain points per variant index, it gets converted to streams when requesting section
        """:type : dict[int,list[tuple]]"""

        Node.__global_node_counter += 1

        # report maximum node count reach point
        if Node.get_global_node_count() > _PL_consts.PREFAB_NODE_COUNT_MAX:
            lprint("W More than maximum allowed number (max: %s) of Control Nodes will be exported, expect problems in game!",
                   (_PL_consts.PREFAB_NODE_COUNT_MAX,))
Example #22
0
def _fill_material_sections(used_materials):
    """
    Fills up "Material" sections.
    :param used_materials:
    :return:
    """
    material_sections = []
    for material_i, material in enumerate(used_materials):
        if material is not None:
            material_section = _SectionData("Material")
            if isinstance(material, str):
                # mat_alias = "_empty_material_"
                mat_alias = str(material + "-_default_settings_")
                lprint('I "%s" material has been used to replace all unspecified materials.', (mat_alias,))
                # effect_name = "eut2.none"
                effect_name = "eut2.dif"
            else:
                shader_data = material.get("scs_shader_attributes", {})
                mat_alias = material.name
                effect_name = shader_data.get('effect', None)
                if not effect_name:
                    mat_alias = str("_" + material.name + "_-_default_settings_")
                    # effect_name = "eut2.none"
                    effect_name = "eut2.dif"
            material_section.props.append(("Alias", mat_alias))
            material_section.props.append(("Effect", effect_name))
            # print('material %i: "%s"' % (material_i, mat_alias))
            material_sections.append(material_section)
    return material_sections
Example #23
0
def get_shader_preset(shader_presets_filepath, template_name):
    """Returns requested Shader Preset data from preset file.

    :param shader_presets_filepath: A file path to SCS shader preset file, can be absolute or relative
    :type shader_presets_filepath: str
    :param template_name: Preset name
    :type template_name: str
    :return: Preset data section
    :rtype: SectionData
    """
    # print('shader_presets_filepath: %r' % shader_presets_filepath)
    if shader_presets_filepath.startswith(str(os.sep + os.sep)):  # IF RELATIVE PATH, MAKE IT ABSOLUTE
        shader_presets_filepath = _path.get_abs_path(shader_presets_filepath)
    preset_section = None
    if os.path.isfile(shader_presets_filepath):
        presets_container = _pix_container.get_data_from_file(shader_presets_filepath, '    ')
        if presets_container:
            for section in presets_container:
                if section.type == "Shader":
                    for prop in section.props:
                        if prop[0] == "PresetName":
                            if prop[1] == template_name:
                                # print(' + template name: "%s"' % template_name)
                                preset_section = section
                                break
    else:
        lprint('\nW The file path "%s" is not valid!', (shader_presets_filepath,))
    return preset_section
Example #24
0
def write_data_to_file(container, filepath, ind, print_info=False):
    """Exports given container in given filepath.

    :param container:
    :type container:
    :param filepath: path to file where container should be exported
    :type filepath: str
    :param ind: intendention for printout
    :type ind: str
    :param print_info: should infos be printed
    :type print_info: bool
    :return: True if export was successfull, otherwise False
    :rtype: bool
    """

    # convert filepath in readable form so when file writting will be logged
    # path will be properly readable even on windows. Without mixed back and forward slashes.
    filepath = _path_utils.readable_norm(filepath)

    result = _pix_writer.write_data(container,
                                    filepath,
                                    ind,
                                    print_info=print_info)
    if result != {'FINISHED'}:
        lprint(
            "E Unable to export data into file:\n\t   %r\n\t   For details check printouts above.",
            (filepath, ))
        return False
    else:
        lprint("I File created!")
        return True
Example #25
0
def update_look_from_material(root_obj, material, preset_change=False):
    """Updates look entry from given material. If look or material inside look doesn't exists update will fail.
    There is also extra option for preset change, which will overwrite shader type specific properties
    on all looks and remove all unused properties from looks.

    :param root_obj: scs root object on which looks are written
    :type root_obj: bpy.types.Object
    :param material: material to update from
    :type material: bpy.types.Material
    :param preset_change: flag indicating if there was preset change
    :type preset_change: bool
    """

    if not root_obj or not material:
        return

    if _MAIN_DICT not in root_obj or not (0 <= root_obj.scs_props.active_scs_look < len(root_obj.scs_object_look_inventory)):
        return

    look_id_str = str(root_obj.scs_object_look_inventory[root_obj.scs_props.active_scs_look].id)

    if look_id_str not in root_obj[_MAIN_DICT]:
        lprint("D Cant't update look! Look entry with ID: %s does not exists in %r", (look_id_str, root_obj.name))
        return

    look_data = root_obj[_MAIN_DICT][look_id_str]
    mat_id_str = str(material.scs_props.id)
    if mat_id_str not in look_data:
        lprint("D Can't update look! Look entry with ID: %s is missing data for material: %r", (look_id_str, material.name))
        return

    new_mat = __create_material_entry__(material)
    look_data[mat_id_str] = new_mat

    # cleanup and sync of all looks
    for look_id in root_obj[_MAIN_DICT]:
        if look_id != look_id_str:

            curr_mat = root_obj[_MAIN_DICT][look_id][mat_id_str]

            for key in curr_mat:

                if preset_change:  # preset change write through

                    if key in ("active_shader_preset_name", "mat_effect_name") or __is_texture_locked__(material, key):  # overwrite
                        curr_mat[key] = new_mat[key]
                    elif key not in new_mat:  # delete if not in newly created material entry
                        del curr_mat[key]

                else:  # general write through

                    overwrite = (key.endswith("_uv"))  # UV mappings, because this property is not look related

                    if overwrite:
                        curr_mat[key] = new_mat[key]

            # additionally add any new properties from current material
            for key in new_mat:
                if key not in curr_mat:
                    curr_mat[key] = new_mat[key]
Example #26
0
def write_data_to_file(container, filepath, ind, print_info=False):
    """Exports given container in given filepath.

    :param container:
    :type container:
    :param filepath: path to file where container should be exported
    :type filepath: str
    :param ind: intendention for printout
    :type ind: str
    :param print_info: should infos be printed
    :type print_info: bool
    :return: True if export was successfull, otherwise False
    :rtype: bool
    """

    # convert filepath in readable form so when file writting will be logged
    # path will be properly readable even on windows. Without mixed back and forward slashes.
    filepath = _path_utils.readable_norm(filepath)

    result = _pix_writer.write_data(container, filepath, ind, print_info=print_info)
    if result != {'FINISHED'}:
        lprint("E Unable to export data into file:\n\t   %r\n\t   For details check printouts above.", (filepath,))
        return False
    else:
        lprint("I File created!")
        return True
Example #27
0
def write_through(root_obj, material, prop):
    """Writes given property from material to all looks within this SCS game object.

    :param root_obj: scs root object from which looks data will be taken
    :type root_obj: bpy.types.Object
    :param material: material from which property value should be taken
    :type material: bpy.types.Material
    :param prop: property string which should be written through
    :type prop: str
    :return: number of overwritten looks; If something goes wrong -1 is returned
    :rtype: int
    """
    if not root_obj or not material:
        return -1

    if _MAIN_DICT not in root_obj or not hasattr(material.scs_props, prop):
        return -1

    written_looks_count = 0

    mat_id_str = str(material.scs_props.id)
    for look_id in root_obj[_MAIN_DICT]:
        curr_look = root_obj[_MAIN_DICT][look_id]

        if not mat_id_str in curr_look or not prop in curr_look[mat_id_str]:
            lprint("D Look with ID: %s is not synced, property %r won't be updated!", (look_id, prop))
            continue

        curr_look[mat_id_str][prop] = getattr(material.scs_props, prop)
        written_looks_count += 1

    return written_looks_count
Example #28
0
    def execute(self, context):
        lprint('D ' + self.bl_label + "...")

        old_scene = None
        if context.scene and context.scene != _LIGHTING_consts.scene_name:
            old_scene = context.scene

        # if scs lighting scene is not present in blend file anymore, we are done
        if _LIGHTING_consts.scene_name not in bpy.data.scenes:
            return {'FINISHED'}

        # firstly remove the lighting scene
        override = context.copy()
        override['window'] = context.window_manager.windows[-1]
        override['scene'] = bpy.data.scenes[_LIGHTING_consts.scene_name]
        bpy.ops.scene.delete(override, 'INVOKE_DEFAULT')

        if _LIGHTING_consts.sun_lamp_name in bpy.data.objects:
            bpy.data.objects.remove(bpy.data.objects[_LIGHTING_consts.sun_lamp_name], do_unlink=True)

        # reset light direction & ambient, diffuse and specular environment values
        _lighting_evaluator_ng.reset_lighting_params()
        _compose_lighting_ng.reset_lighting_params()
        _add_env_ng.reset_lighting_params()

        # while we delete one scene blender might/will select first available as current,
        # so we have to force our screen to be using old scene again
        if old_scene and context.window:
            context.window.scene = old_scene

        return {'FINISHED'}
Example #29
0
def __clean_node_tree__(node_tree):
    """Cleans material node tree of any nodes, custom properties and even cleanup any unused dummy normal map materials.

    :param node_tree: node tree on which any shader nodes should be deleted
    :type node_tree: bpy.types.NodeTree
    """

    mats_to_remove = []
    for node in node_tree.nodes:
        if node.type == "MATERIAL" and node.material and node.material.name.startswith(".scs_nmap_"):
            mats_to_remove.append(node.material.name)

    # clean nodes and custom props
    node_tree.nodes.clear()
    for key in node_tree.keys():
        del node_tree[key]

    # clean unused dummy normal map materials
    mat_i = 0
    while mat_i < len(mats_to_remove):

        mat_name = mats_to_remove[mat_i]

        if mat_name in bpy.data.materials and bpy.data.materials[mat_name].users == 0:
            lprint("D Removing unused nmap material: %s", (mat_name,))
            bpy.data.materials.remove(bpy.data.materials[mat_name])

        mat_i += 1
Example #30
0
    def cancel(self, context):

        # reset static variables
        SCSPathsInitialization.__static_message = ""
        SCSPathsInitialization.__static_paths_list.clear()

        # try to reset timer if window manager is available
        if len(bpy.data.window_managers) > 0:
            wm = bpy.data.window_managers[0]
            wm.event_timer_remove(SCSPathsInitialization.__static_timer)
            SCSPathsInitialization.__static_timer = None

        # report finished progress to 3d view report operator
        if int(_get_scs_globals().dump_level) < self.DUMP_LEVEL:
            bpy.ops.wm.show_3dview_report('INVOKE_DEFAULT',
                                          abort=True,
                                          is_progress_message=True)

        # when done, tag everything for redraw in the case some UI components
        # are reporting status of this operator
        _view3d_utils.tag_redraw_all_regions()

        # as last invoke any callbacks and afterwards delete them
        while len(SCSPathsInitialization.__static_callbacks) > 0:

            callback = SCSPathsInitialization.__static_callbacks[0]

            callback()
            SCSPathsInitialization.__static_callbacks.remove(callback)

        lprint("D Paths initialization cancel invoked!")
Example #31
0
def __get_shader__(effect, report_not_found, mat_name):
    """Get shader from effect name. If it doesn't find any suitable shader it returns "dif.spec" shader from euro trucks 2 library.

    :param effect: whole effect name of shader
    :type effect: str
    :param report_not_found: flag indicating if special warning should be reported if no proper shader is found
    :type report_not_found: bool
    :param mat_name: name of material for which shader will be used (NOTE: only for reporting in the case of not found shader)
    :type mat_name: str
    :return: corresponding class of shader for given effect is returned; if not found "eut2.dif.spec" is returned
    :rtype: class
    """

    shaderclass = None
    if effect.startswith("eut2."):

        from io_scs_tools.internals.shaders import eut2

        shaderclass = eut2.get_shader(effect[5:])

    if not shaderclass:  # fallback

        if report_not_found:
            lprint("W Shader %r used on material %r\n\t   "
                   "is not implemented in Blender,\n\t   "
                   "3D viewport shading will fallback to 'dif.spec'",
                   (effect, mat_name))

        from io_scs_tools.internals.shaders.eut2.dif_spec import DifSpec

        return DifSpec

    return shaderclass
Example #32
0
    def invoke(self, context, event):

        self.__last_time = time(
        )  # reset last time now as everything starts again
        SCSPathsInitialization.__static_paths_done = 0  # reset done paths counter as everything starts here

        # engage abortion of any running instances
        SCSPathsInitialization.__abort_any_running_instances = True

        # now fill up new paths to static inventory
        for filepath_prop in self.paths_list:

            # sort out only unique paths and merge them with current static path list
            old_item = None
            for item in SCSPathsInitialization.__static_paths_list:
                if item["attr"] == filepath_prop.attr:
                    old_item = item
                    break

            # if old item is found just reuse it instead of adding new item to list
            if old_item:
                old_item["name"] = filepath_prop["name"]
                old_item["path"] = filepath_prop["path"]
            else:
                SCSPathsInitialization.__static_paths_list.append({
                    "name":
                    filepath_prop["name"],
                    "attr":
                    filepath_prop["attr"],
                    "path":
                    filepath_prop["path"]
                })

        # update paths counter to the current paths list length
        SCSPathsInitialization.__static_paths_count = len(
            SCSPathsInitialization.__static_paths_list)

        # now as paths list is updated and we are about to run our instance
        # release switch that should be aborting all the rest of operator instances
        SCSPathsInitialization.__abort_any_running_instances = False

        SCSPathsInitialization.__static_message = "Starting initialization...\n"
        bpy.ops.wm.show_3dview_report(
            'INVOKE_DEFAULT',
            message=SCSPathsInitialization.__static_message,
            hide_controls=True,
            is_progress_message=True)

        wm = bpy.data.window_managers[0]
        window = wm.windows[0]

        # in case any operator was previously invoked we have to remove timer before adding new
        if SCSPathsInitialization.__static_timer:
            wm.event_timer_remove(SCSPathsInitialization.__static_timer)

        SCSPathsInitialization.__static_timer = wm.event_timer_add(0.2, window)

        wm.modal_handler_add(self)
        lprint("I Paths initialization started...")
        return {'RUNNING_MODAL'}
Example #33
0
def aux_to_node_color(aux_prop, from_index=0):
    """Converts auxiliary item to color ready for assigning to Blender nodes.
    1. Converts auxiliary item to color
    2. Sets minimal HSV value attribute for rendering
    3. Applies pre gamma correction
    4. Returns it as tuple of 4 floats RGBA

    :param aux_prop:
    :type aux_prop: bpy.props.IDPropertyGroup
    :param from_index: index in aux property collection from which to start taking RGB values
    :type from_index: int
    :return: RGBA as tuple of floats
    :rtype: tuple[float]
    """

    col = []
    for i, aux_item in enumerate(aux_prop):

        if from_index <= i < from_index + 3:
            col.append(max(0, aux_item['value']))

    # just make sure to fill empty RGB channels so game won't complain
    if len(col) < 3:
        col.extend([0, ] * (3 - len(col)))
        lprint("D Filling 0.0 for missing auxiliary item values of RGB color presentation (Actual/needed count: %s/3)",
               (len(aux_prop),))

    return to_node_color(col)
Example #34
0
def _get_objects_by_type(blender_objects, parts):
    """Gets lists for different types of objects used by SCS.
    It actually returns: mesh objects, locators (prefab, model, collision) and armature object.

    :param blender_objects: list of the objects that should be sorted by type
    :type blender_objects: list of bpy.types.Object
    :param parts: transitional parts class instance for adding users (parts without users won't be exported)
    :type parts: io_scs_tools.exp.transition_structs.parts.PartsTrans
    :return: more lists of objects in order: meshes, prefab_locators, model_locators, collision_locators and armutare object as last
    :rtype: list of [list]
    """

    prefab_locator_list = []
    model_locator_list = []
    collision_locator_list = []
    mesh_object_list = []
    armature_object = None

    for obj in blender_objects:

        # LOCATORS
        if obj.type == 'EMPTY':
            if obj.scs_props.locator_type == 'Prefab':
                prefab_locator_list.append(obj)

                if _object_utils.has_part_property(obj):
                    parts.add_user(obj)

            elif obj.scs_props.locator_type == 'Model':
                model_locator_list.append(obj)

                parts.add_user(obj)

            elif obj.scs_props.locator_type == 'Collision':
                collision_locator_list.append(obj)

                parts.add_user(obj)

        # ARMATURES
        elif obj.type == 'ARMATURE':
            if not armature_object:
                armature_object = obj
            else:
                lprint(
                    "W More armatures detected on SCS Root object, only first one will be used!"
                )

        # MESHES
        elif obj.type == 'MESH':

            # MESH OBJECTS
            if obj.data.scs_props.locator_preview_model_path == "":  # Export object only if it's not a Preview Model...
                mesh_object_list.append(obj)

                parts.add_user(obj)

        else:
            print('!!! - Unhandled object type: %r' % str(obj.type))

    return mesh_object_list, prefab_locator_list, model_locator_list, collision_locator_list, armature_object
Example #35
0
def switch_layers_visibility(storage_list, show):
    """Switches visibility of layers in Blender. If show is True all layers on current scene
        and local layers of current 3D spaces are shown. If storage_list is provided it tries
        to restore visibilites from entries.

        WARNING: this function can restore only storage_list which was created with this function
        otherwise it may raise error.

    :param storage_list: list where previous layers visibility states are or should be stored into
    :type storage_list: list
    :param show: flag for indicating if all layers should be shown (value True) or restored (value False)
    :type show: bool
    :return: states of layers visibilites for scene and local layers of views
    :rtype: list of list(bool*20)
    """

    for space in get_all_spaces():
        if show:
            storage_list.append(list(space.layers))
            space.layers = [True] * 20
            lprint("D Layers visibility set to True")
        elif len(storage_list) > 0:
            space.layers = storage_list[0]
            storage_list = storage_list[1:]

    scene = bpy.context.scene
    if show:
        storage_list.append(list(scene.layers))
        scene.layers = [True] * 20
    elif len(storage_list) > 0:
        scene.layers = storage_list[0]
        storage_list = storage_list[1:]

    return storage_list
Example #36
0
def _get_part(section):
    name = None
    pieces = []
    locators = []
    for prop in section.props:
        if prop[0] in ("", "#"):
            pass
        elif prop[0] == "Name":
            name = prop[1]
        elif prop[0] == "PieceCount":
            pass
        elif prop[0] == "LocatorCount":
            pass
        elif prop[0] == "Pieces":
            pieces = prop[1]
        elif prop[0] == "Locators":
            locators = prop[1]
        else:
            lprint('\nW Unknown property in "Global" data: "%s"!', prop[0])
    if not isinstance(pieces, list):
        if isinstance(pieces, int):
            pieces = [pieces]
    if not isinstance(locators, list):
        if isinstance(locators, int):
            locators = [locators]

    return name, pieces, locators
Example #37
0
def export(scs_root_obj, armature, scs_animation, dirpath, skeleton_filepath):
    """Exports PIA animation

    :param scs_root_obj: root object of current animation
    :type scs_root_obj: bpy.types.Object
    :param armature: armature object of current animation
    :type armature: bpy.types.Object
    :param scs_animation: animation which should get exported
    :type scs_animation: io_scs_tools.properties.object.ObjectAnimationInventory
    :param dirpath: path to export
    :type dirpath: str
    :param skeleton_filepath: name of skeleton file that this animation works on
    :type skeleton_filepath: str
    """

    # safety checks
    if scs_animation.action not in bpy.data.actions:
        lprint(str("E Action %r requested by %r animation doesn't exists. Animation won't be exported!\n\t   "
                   "Make sure proper action is assigned to SCS Animation."),
               (scs_animation.action, scs_animation.name))
        return False

    scs_globals = _get_scs_globals()
    print("\n************************************")
    print("**      SCS PIA Exporter          **")
    print("**      (c)2014 SCS Software      **")
    print("************************************\n")

    # DATA GATHERING
    total_time = scs_animation.length
    action = bpy.data.actions[scs_animation.action]
    bone_channels = _get_bone_channels(scs_root_obj, armature, scs_animation, action, scs_globals.export_scale)
    custom_channels = _get_custom_channels(scs_animation, action)

    # DATA CREATION
    header_section = _fill_header_section(scs_animation.name, scs_globals.sign_export)
    custom_channel_sections = _fill_channel_sections(custom_channels, "CustomChannel")
    bone_channel_sections = _fill_channel_sections(bone_channels, "BoneChannel")
    global_section = _fill_global_section(skeleton_filepath, total_time, len(bone_channels), len(custom_channels))

    # post creation safety checks
    if len(bone_channels) + len(custom_channels) == 0:
        lprint(str("E PIA file won't be exported, as SCS Animation %r\n\t   "
                   "doesn't effect armature or it's bones or data are invalid."),
               (scs_animation.name,))
        return False

    # DATA ASSEMBLING
    pia_container = [header_section, global_section]
    for section in custom_channel_sections:
        pia_container.append(section)
    for section in bone_channel_sections:
        pia_container.append(section)

    # FILE EXPORT
    ind = "    "
    filepath = os.path.join(dirpath, scs_animation.name + ".pia")

    # print("************************************")
    return _pix_container.write_data_to_file(pia_container, filepath, ind)
Example #38
0
    def set_output_lane(self, index, curve_index):
        """Set the curve index for given output lane.

        NOTE: there is no safety check for curve index, so if curve won't exist
        in PIP file data will be invalid

        :param index: index of lane (0 - inner most)
        :type index: int
        :param curve_index: curve index in exported data
        :type curve_index: int
        :return: True if outpuit lane is properly set; False if lane index is out of range
        :rtype: bool
        """

        if index < 0 or index >= _PL_consts.PREFAB_LANE_COUNT_MAX:
            lprint(
                "D Output lane index out of range, expected [0-%s]; got index: %s",
                (
                    _PL_consts.PREFAB_LANE_COUNT_MAX,
                    index,
                ))
            return False

        if self.__output_lanes[index] != -1:
            lprint(
                "W Multiple curves use Boundary: 'Output - Lane %s' on Boundary Node: %s, only one will be used!",
                (index, self.__index))

        self.__output_lanes[index] = curve_index
        return True
Example #39
0
def add_look(root_obj, look_id):
    """Creates and adds look with given ID to SCS root object.
    If look is not yet in dictionary it will be added otherwise nothing will be done.
    NOTE: new look collects values from curent material values

    :param root_obj: scs root object on which new look should be added
    :type root_obj: bpy.types.Object
    :param look_id: ID of new look
    :type look_id: int
    """

    if not root_obj:
        return

    # init if not yet done
    if _MAIN_DICT not in root_obj:
        root_obj[_MAIN_DICT] = {}

    look_id_str = str(look_id)
    if look_id_str not in root_obj[_MAIN_DICT]:
        new_look = {}

        for material in __collect_materials__(root_obj):
            mat_id_str = str(material.scs_props.id)
            new_look[mat_id_str] = __create_material_entry__(material)

        root_obj[_MAIN_DICT][look_id_str] = new_look
        lprint("D Look with id %r added to %r", (look_id_str, root_obj.name))
Example #40
0
def fix_visibility(locator):
    """Fix layers visibility and hide property for preview model on given locator

    :param locator: locator object for which preview model layers should synced
    :type locator: bpy.types.Object
    """

    prevm_id = _cache.get_entry(locator.name)

    if prevm_id:

        # make sure that preview model is uncached if doesn't exists anymore
        if prevm_id not in bpy.data.objects:
            lprint("D Fix layers from preview model will uncache %r", (prevm_id,))
            _cache.delete_entry(prevm_id)
            return

        prevm_obj = bpy.data.objects[prevm_id]

        # layers check
        if list(prevm_obj.layers) != list(locator.layers):
            prevm_obj.layers = tuple(locator.layers)

        # hide property check
        if prevm_obj.hide != locator.hide:
            prevm_obj.hide = locator.hide
Example #41
0
def add_materials(root_obj, mat_list):
    """Adds material entries to all of the looks in given SCS root object.
    Only none existing materials from given list are added.

    :param root_obj: scs root object on which looks datablock new materials should be added
    :type root_obj: bpy.types.Object
    :param mat_list: list of blender materials that should be added
    :type mat_list: iter of bpy.types.Material
    """

    if not root_obj or not mat_list:
        return

    if _MAIN_DICT not in root_obj or len(root_obj[_MAIN_DICT]) <= 0:
        return

    existing_mats_ids = root_obj[_MAIN_DICT][root_obj[_MAIN_DICT].keys()[0]].keys()
    new_mats_added = 0
    for new_mat in mat_list:

        new_mat_id_str = str(new_mat.scs_props.id)

        # add material to looks only if it doesn't yet exists in dictionary
        if new_mat_id_str not in existing_mats_ids:

            # add new entry to all of the looks
            for look_id in root_obj[_MAIN_DICT]:
                root_obj[_MAIN_DICT][look_id][new_mat_id_str] = __create_material_entry__(new_mat)

            new_mats_added += 1

    lprint("D %s/%s (actual/requested) new materials added to looks dictionary in %r", (new_mats_added, len(mat_list), root_obj.name))
Example #42
0
def get_addon_installation_paths():
    """Returns a list of paths to the directories where the addon can be installed."""
    script_paths = bpy.utils.script_paths()
    addon_dirs = ('addons', 'addons_contrib')
    script_locations = []

    for script_path in script_paths:
        for addon_dir in addon_dirs:
            script_locations.append(
                os.path.join(script_path, addon_dir, 'io_scs_tools'))

    scs_installation_dirs = []
    for location in script_locations:
        if os.path.isdir(location):
            scs_installation_dirs.append(location)

    if len(scs_installation_dirs) == 0:
        lprint(
            '''\n\nE The installation directory of "SCS Blender Tools" couldn't be detected! (Shouldn't happen!)\n'''
        )
    elif len(scs_installation_dirs) > 1:
        lprint(
            '\n\nW More than one installation of "SCS Blender Tools" detected!\n\t  Please remove redundant installations so the only one '
            'remain.\n')

    return scs_installation_dirs
Example #43
0
def clean_unused(root_obj):
    """Removes all unused material entries from looks dictionary in given SCS root object.

    :param root_obj: scs root object which should be cleaned
    :type root_obj: bpy.types.Object
    """
    if not root_obj:
        return

    if _MAIN_DICT not in root_obj or len(root_obj[_MAIN_DICT]) <= 0:
        return

    # create unused materials id list with removing used materials ids from exisiting
    unused_mats_ids = list(root_obj[_MAIN_DICT][root_obj[_MAIN_DICT].keys()[0]].keys())
    for mat in __collect_materials__(root_obj):

        mat_id_str = str(mat.scs_props.id)
        if mat_id_str in unused_mats_ids:
            unused_mats_ids.remove(mat_id_str)

    # remove unused material entry from every look
    for unused_mat_id in unused_mats_ids:
        for look_id in root_obj[_MAIN_DICT]:

            look_data = root_obj[_MAIN_DICT][look_id]

            if unused_mat_id in look_data:
                del look_data[unused_mat_id]

    lprint("D %s material entries cleaned from looks dictionary in %r", (len(unused_mats_ids), root_obj.name))
Example #44
0
def write_data(container, filepath, ind='    ', print_on_success=True, print_info=0):
    """This function is called from outside of this script. It takes
    data container, file path and string of indentation characters
    and it saves all data to the file."""
    # print_info = 0 ## Debug printouts
    orig_ind = ind

    # WRITE TO FILE
    file = open(filepath, "w", encoding="utf8", newline="\n")
    fw = file.write
    if print_on_success:
        lprint('I WRITTING PIX FILE to: %r', (filepath,))

    for section in container:
        if section.type != "#comment":
            fw('%s {\n' % section.type)
            if print_info:
                print('SEC.: "%s"' % section.type)
            _write_properties_and_data(fw, section, ind, print_info)
            for sec in section.sections:
                _write_section(fw, sec, ind, orig_ind, print_info)
            fw('}\n')
        else:
            for comment in section.props:
                fw('%s\n' % comment[1])
    fw('\n')
    file.close()

    return {'FINISHED'}
Example #45
0
def export(filepath, texture_name, settings):
    """Exports TOBJ with settings.

    :param filepath: absolute file path with name for TOBJ
    :type filepath: str
    :param texture_name: name of texture file
    :type texture_name: str
    :param settings: settings of texture saved in material.scs_props
    :type settings: set
    :return: True if file was written successfully; False otherwise
    """

    # try to load tobj container from file path
    # to be able to keep all the settings from before
    # and overwrite only what settings we support
    container = None
    if os.path.isfile(filepath):
        container = _TobjContainer.read_data_from_file(filepath)

    # if container for some reason wasn't loaded create new one
    if container is None:
        container = _TobjContainer()
        container.map_type = "2d"
        if texture_name is not None:
            container.map_names.append(texture_name)

    # change settings only on supported 2d texture type
    if container.map_type == "2d":

        # MAP NAMES
        # try to change map names with current texture name
        # otherwise add new value
        if len(container.map_names) > 0:
            container.map_names[0] = texture_name
        elif texture_name is not None:
            container.map_names.append(texture_name)

        # ADDR
        if "u_repeat" in settings:
            addr_u = "repeat"
        else:
            addr_u = "clamp_to_edge"

        if "v_repeat" in settings:
            addr_v = "repeat"
        else:
            addr_v = "clamp_to_edge"

        container.addr.clear()
        container.addr.append(addr_u)
        container.addr.append(addr_v)

        # USAGE
        container.usage = "tsnormal" if "tsnormal" in settings else ""

    else:

        lprint("D Ignoring TOBJ settings save as TOBJ is featuring non 2d map type!")

    return container.write_data_to_file(filepath)