Beispiel #1
0
    def update_shader_presets(self, context):
        """
        Returns the actual Shader name list from "scs_shader_presets_inventory".
        It also updates "shader_presets_container", so the UI could contain all
        the items with no error. (necessary hack :-/)
        :param context:
        :return:
        """

        items = [(
            "<none>", "<none>",
            "No SCS shader preset in use (may result in incorrect model output)",
            'X_VEC', 0)]

        # print('  > update_shader_presets...')

        # save dictionary of preset names references in globals so that UI doesn't mess up strings
        if not "shader_presets_container" in globals():
            global shader_presets_container
            shader_presets_container = GlobalSCSProps.ShaderNamesDictionary()
            # print("Presets container created!")

        if self.shader_preset_list_sorted:
            inventory = {}
            for preset_i, preset in enumerate(_get_shader_presets_inventory()):
                inventory[preset.name] = preset_i
            for preset in sorted(inventory):
                preset_i = inventory[preset]
                act_preset = shader_presets_container.add(preset)
                # print(' + %i act_preset: %s (%s)' % (preset_i, str(act_preset), str(preset)))
                icon_str = GlobalSCSProps.get_shader_icon_str(act_preset)
                if icon_str is not None:  # if None then it's <none> preset which is already added
                    items.append(
                        (act_preset, act_preset, "", icon_str, preset_i))
        else:
            for preset_i, preset in enumerate(_get_shader_presets_inventory()):
                act_preset = shader_presets_container.add(preset.name)
                # print(' + %i act_preset: %s (%s)' % (preset_i, str(act_preset), str(preset)))
                icon_str = GlobalSCSProps.get_shader_icon_str(act_preset)
                if icon_str is not None:  # if None then it's <none> preset which is already added
                    items.append(
                        (act_preset, act_preset, "", icon_str, preset_i))
        return items
Beispiel #2
0
    def update_shader_preset_search_value(self, context):

        if self.shader_preset_search_value != "":

            for preset_i, preset in enumerate(_get_shader_presets_inventory()):

                if self.shader_preset_search_value == preset.name:
                    self.set_shader_presets_item(preset_i)

            self.shader_preset_search_value = ""
            self.shader_preset_use_search = False
Beispiel #3
0
    def set_shader_presets_item(self, value):
        """
        Receives an actual index of currently selected Shader preset name in the menu,
        sets that Shader name as active in active Material.
        :param value:
        :return:
        """

        material = bpy.context.active_object.active_material
        if value == 0:  # No Shader...
            material.scs_props.active_shader_preset_name = "<none>"
            material.scs_props.mat_effect_name = "None"

            # reset material nodes when user selects none shader
            if material.node_tree:
                material.node_tree.nodes.clear()
                material.use_nodes = False

            material["scs_shader_attributes"] = {}
        else:
            for preset_i, preset in enumerate(_get_shader_presets_inventory()):
                if value == preset_i:

                    # Set Shader Preset in the Material
                    preset_section = _material_utils.get_shader_preset(
                        _get_scs_globals().shader_presets_filepath,
                        preset.name)

                    if preset_section:
                        preset_name = preset_section.get_prop_value(
                            "PresetName")
                        preset_effect = preset_section.get_prop_value("Effect")
                        material.scs_props.mat_effect_name = preset_effect

                        if preset_name:
                            _material_utils.set_shader_data_to_material(
                                material, preset_section)
                            material.scs_props.active_shader_preset_name = preset_name
                        else:
                            material.scs_props.active_shader_preset_name = "<none>"
                            material["scs_shader_attributes"] = {}
                            print('    NO "preset_name"!')
                            # if preset_effect:
                            # print('      preset_effect: "%s"' % preset_effect)
                            # if preset_flags:
                            # print('      preset_flags: "%s"' % preset_flags)
                            # if preset_attribute_cnt:
                            # print('      preset_attribute_cnt: "%s"' % preset_attribute_cnt)
                            # if preset_texture_cnt:
                            # print('      preset_texture_cnt: "%s"' % preset_texture_cnt)
                    else:
                        print('''NO "preset_section"! (Shouldn't happen!)''')
                else:
                    preset.active = False
Beispiel #4
0
        def execute(self, context):
            lprint("I " + self.bl_label + "...")

            from io_scs_tools.internals.shader_presets import cache as _shader_presets_cache
            from io_scs_tools.utils import get_shader_presets_inventory as _get_shader_presets_inventory

            mat = context.material
            mat_scs_props = mat.scs_props
            """:type: io_scs_tools.properties.material.MaterialSCSTools"""
            preset = _get_shader_presets_inventory()[mat_scs_props.active_shader_preset_name]
            """:type: io_scs_tools.properties.world.ShaderPresetsInventoryItem"""

            # extract only flavor effect part of string
            flavor_effect_part = mat_scs_props.mat_effect_name[len(preset.effect):]

            new_flavor_state = not self.flavor_enabled
            flavors_suffix = ""
            for flavor in preset.flavors:
                flavor_variant_found = False
                for flavor_variant in flavor.variants:

                    if flavor_variant.name == self.flavor_name:
                        # add founded flavor to flavors suffix only if enabled
                        if new_flavor_state:
                            flavors_suffix += "." + flavor_variant.name

                        flavor_variant_found = True
                        break

                # if one variant of flavor is found skip all other variants
                if flavor_variant_found:
                    continue

                # make sure to add all other enabled flavors to flavors suffix
                for flavor_variant in flavor.variants:

                    is_in_middle = "." + flavor_variant.name + "." in flavor_effect_part
                    is_on_end = flavor_effect_part.endswith("." + flavor_variant.name)

                    if is_in_middle or is_on_end:
                        flavors_suffix += "." + flavor_variant.name

            # finally set new shader data to material
            section = _shader_presets_cache.get_section(preset, flavors_suffix)
            context.material.scs_props.mat_effect_name = preset.effect + flavors_suffix
            _material_utils.set_shader_data_to_material(context.material, section)

            # sync shader types on all scs roots by updating looks on them
            # to avoid different shader types on different scs roots for same material
            for scs_root in _object_utils.gather_scs_roots(bpy.data.objects):
                _looks.update_look_from_material(scs_root, mat, True)

            return {'FINISHED'}
Beispiel #5
0
        def execute(self, context):
            lprint("I " + self.bl_label + "...")

            from io_scs_tools.internals.shader_presets import cache as _shader_presets_cache
            from io_scs_tools.utils import get_shader_presets_inventory as _get_shader_presets_inventory

            mat = context.material
            mat_scs_props = mat.scs_props
            """:type: io_scs_tools.properties.material.MaterialSCSTools"""
            preset = _get_shader_presets_inventory()[
                mat_scs_props.active_shader_preset_name]
            """:type: io_scs_tools.properties.world.ShaderPresetsInventoryItem"""

            # extract only flavor effect part of string
            flavor_effect_part = mat_scs_props.mat_effect_name[len(preset.
                                                                   effect):]

            new_flavor_state = not self.flavor_enabled
            flavors_suffix = ""
            for flavor in preset.flavors:
                flavor_variant_found = False
                for flavor_variant in flavor.variants:

                    if flavor_variant.name == self.flavor_name:
                        # add founded flavor to flavors suffix only if enabled
                        if new_flavor_state:
                            flavors_suffix += "." + flavor_variant.name

                        flavor_variant_found = True
                        break

                # if one variant of flavor is found skip all other variants
                if flavor_variant_found:
                    continue

                # make sure to add all other enabled flavors to flavors suffix
                for flavor_variant in flavor.variants:

                    is_in_middle = "." + flavor_variant.name + "." in flavor_effect_part
                    is_on_end = flavor_effect_part.endswith(
                        "." + flavor_variant.name)

                    if is_in_middle or is_on_end:
                        flavors_suffix += "." + flavor_variant.name

            # finally set new shader data to material
            section = _shader_presets_cache.get_section(preset, flavors_suffix)
            context.material.scs_props.mat_effect_name = preset.effect + flavors_suffix
            _material_utils.set_shader_data_to_material(
                context.material, section)

            return {'FINISHED'}
Beispiel #6
0
    def get_shader_presets_item(self):
        """
        Returns menu index of a Shader preset name of actual Material to set
        the right name in UI menu.
        :return:
        """
        # print('  > get_shader_presets_items...')
        material = bpy.context.active_object.active_material
        result = 0

        for preset_i, preset in enumerate(_get_shader_presets_inventory()):
            if preset.name == material.scs_props.active_shader_preset_name:
                result = preset_i

        return result
Beispiel #7
0
def _draw_shader_flavors(layout, mat):
    """Draws shader flavors if any.

    :param layout: layout to draw on
    :type layout: bpy.types.UILayout
    :param mat: material for which flavors should be drawn
    :type mat: bpy.types.Material
    """

    if mat.scs_props.active_shader_preset_name == "<none>":
        return

    for preset in _get_shader_presets_inventory():
        if preset.name == mat.scs_props.active_shader_preset_name:

            # strip of base effect name, to avoid any flavor matching in base effect name
            effect_flavor_part = mat.scs_props.mat_effect_name[len(preset.
                                                                   effect):]

            if len(preset.flavors) > 0:

                column = layout.box().column(align=True)
                column.alignment = "LEFT"

            for flavor in preset.flavors:

                row = column.row(align=True)

                for flavor_variant in flavor.variants:

                    is_in_middle = "." + flavor_variant.name + "." in effect_flavor_part
                    is_on_end = effect_flavor_part.endswith(
                        "." + flavor_variant.name)

                    icon = "FILE_TICK" if is_in_middle or is_on_end else "X"
                    props = row.operator("material.scs_switch_flavor",
                                         text=flavor_variant.name,
                                         icon=icon)
                    props.flavor_name = flavor_variant.name
                    props.flavor_enabled = is_in_middle or is_on_end

            # once preset was found just use return to skip other presets
            return
Beispiel #8
0
def _draw_shader_flavors(layout, mat):
    """Draws shader flavors if any.

    :param layout: layout to draw on
    :type layout: bpy.types.UILayout
    :param mat: material for which flavors should be drawn
    :type mat: bpy.types.Material
    """

    if mat.scs_props.active_shader_preset_name == "<none>":
        return

    for preset in _get_shader_presets_inventory():
        if preset.name == mat.scs_props.active_shader_preset_name:

            # strip of base effect name, to avoid any flavor matching in base effect name
            effect_flavor_part = mat.scs_props.mat_effect_name[len(preset.effect):]

            if len(preset.flavors) > 0:

                column = layout.box().column(align=True)
                column.alignment = "LEFT"

            for flavor in preset.flavors:

                row = column.row(align=True)

                for flavor_variant in flavor.variants:

                    is_in_middle = "." + flavor_variant.name + "." in effect_flavor_part
                    is_on_end = effect_flavor_part.endswith("." + flavor_variant.name)

                    icon = "FILE_TICK" if is_in_middle or is_on_end else "X"
                    props = row.operator("material.scs_switch_flavor", text=flavor_variant.name, icon=icon)
                    props.flavor_name = flavor_variant.name
                    props.flavor_enabled = is_in_middle or is_on_end

            # once preset was found just use return to skip other presets
            return
Beispiel #9
0
def post_load(scene):
    # get Blender Tools version from last blend file load
    last_load_bt_ver = _get_scs_globals().last_load_bt_version

    scs_roots = None
    """
    Applies fixes for v0.6 or less:
    1. fixes reflection textures tga's for tobjs as TOBJ load is now supported and unlock that textures
    2. calls update on all set textures to correct paths for them
    3. tries to fix active shader preset name for materials, because of new flavor system
    """
    if _info_utils.cmp_ver_str(last_load_bt_ver, "0.6") <= 0:

        print("INFO\t-  Applying fixes for version <= 0.6")

        for material in bpy.data.materials:

            # ignore materials not related to blender tools
            if material.scs_props.mat_effect_name == "":
                continue

            for tex_type in material.scs_props.get_texture_types().keys():

                texture_attr_str = "shader_texture_" + tex_type
                if texture_attr_str in material.scs_props.keys():

                    # 1. fix reflection textures
                    if tex_type == "reflection":

                        is_building_ref = material.scs_props[
                            texture_attr_str].endswith("/bulding_ref.tga")
                        is_generic_s = material.scs_props[
                            texture_attr_str].endswith(
                                "material/environment/generic_s.tga")
                        is_glass_interior = material.scs_props.active_shader_preset_name == "glass - interior"
                        is_dif_spec_weight_add_env = material.scs_props.active_shader_preset_name == "dif.spec.weight.add.env"
                        is_truckpaint = material.scs_props.active_shader_preset_name.startswith(
                            "truckpaint")

                        # fix paths
                        if is_building_ref:
                            material.scs_props[
                                texture_attr_str] = material.scs_props[
                                    texture_attr_str][:-4]
                            material.scs_props[texture_attr_str +
                                               "_locked"] = False
                        elif is_generic_s:
                            if is_glass_interior:
                                material.scs_props[
                                    texture_attr_str] = "//material/environment/interior_reflection"
                            elif is_dif_spec_weight_add_env:
                                material.scs_props[
                                    texture_attr_str] = "//material/environment/generic_reflection"
                            else:
                                material.scs_props[
                                    texture_attr_str] = "//material/environment/vehicle_reflection"

                            # unlock reflection textures everywhere except on truckpaint shader
                            if not is_truckpaint:
                                material.scs_props[texture_attr_str +
                                                   "_locked"] = False

                        # acquire roots on demand only once
                        scs_roots = _object_utils.gather_scs_roots(
                            bpy.data.objects) if not scs_roots else scs_roots

                        # propagate reflection texture change on all of the looks.
                        # NOTE: We can afford write through because old BT had all reflection textures locked
                        # meaning user had to use same texture on all looks
                        # NOTE#2: Printouts like:
                        # "Look with ID: X doesn't have entry for material 'X' in SCS Root 'X',
                        #  property 'shader_texture_reflection' won't be updated!"
                        # are expected here, because we don't use any safety check,
                        # if material is used on the mesh objects inside scs root
                        for scs_root in scs_roots:
                            _looks.write_through(scs_root, material,
                                                 texture_attr_str)

                    # 2. trigger update function for path reload and reload of possible missing textures
                    update_func = getattr(material.scs_props,
                                          "update_" + texture_attr_str, None)
                    if update_func:
                        update_func(material)

            # ignore already properly set materials
            if material.scs_props.active_shader_preset_name in _get_shader_presets_inventory(
            ):
                continue

            # 3. try to recover "active_shader_preset_name" from none flavor times Blender Tools
            material_textures = {}
            if "scs_shader_attributes" in material and "textures" in material[
                    "scs_shader_attributes"]:
                for texture in material["scs_shader_attributes"][
                        "textures"].values():
                    tex_id = texture["Tag"].split(":")[1]
                    tex_value = texture["Value"]
                    material_textures[tex_id] = tex_value

            (preset_name, preset_section) = _material_utils.find_preset(
                material.scs_props.mat_effect_name, material_textures)
            if preset_name:
                material.scs_props.active_shader_preset_name = preset_name

                # acquire roots on demand only once
                scs_roots = _object_utils.gather_scs_roots(
                    bpy.data.objects) if not scs_roots else scs_roots

                # make sure to fix active preset shader name in all looks
                # NOTE: Printouts like:
                # "Look with ID: X doesn't have entry for material 'X' in SCS Root 'X',
                #  property 'active_shader_preset_name' won't be updated!"
                # are expected here, because we don't use any safety check,
                # if material is used on the mesh objects inside scs root
                for scs_root in scs_roots:
                    _looks.write_through(scs_root, material,
                                         "active_shader_preset_name")

    # as last update "last load" Blender Tools version to current
    _get_scs_globals().last_load_bt_version = get_tools_version()
Beispiel #10
0
def export(root_object, filepath, used_materials, used_parts):
    """Export PIT.

    :param root_object: SCS root object
    :type root_object: bpy.types.Object
    :param filepath: PIT file path
    :type filepath: str
    :param used_materials: materials transitional structure for accessing stored materials from PIM
    :type used_materials: io_scs_tools.exp.transition_structs.materials.MaterialsTrans
    :param used_parts: parts transitional structure for accessing stored parts from PIM, PIC and PIP
    :type used_parts: io_scs_tools.exp.transition_structs.parts.PartsTrans
    :return: True if successful; False otherwise;
    :rtype: bool
    """

    scs_globals = _get_scs_globals()
    output_type = scs_globals.output_type

    file_name = root_object.name

    print("\n************************************")
    print("**      SCS PIT Exporter          **")
    print("**      (c)2014 SCS Software      **")
    print("************************************\n")

    # DATA GATHERING
    look_list = []
    variant_list = []

    saved_active_look = root_object.scs_props.active_scs_look
    looks_inventory = root_object.scs_object_look_inventory
    looks_count = len(looks_inventory)
    if looks_count <= 0:
        looks_count = 1

    used_materials_pairs = used_materials.get_as_pairs()
    for i in range(0, looks_count):

        # apply each look from inventory first
        if len(looks_inventory) > 0:
            root_object.scs_props.active_scs_look = i

            # actually write values to material because Blender might not refresh data yet
            _looks.apply_active_look(root_object)

            curr_look_name = looks_inventory[i].name
        else:  # if no looks create default
            curr_look_name = "default"

        material_dict = {}
        material_list = []
        # get materials data
        for material_name, material in used_materials_pairs:
            if material is None:
                material_name = str("_default_material_-_default_settings_")

                # DEFAULT MATERIAL
                material_export_data = _default_material(material_name)
                material_list.append(material_name)

            else:
                # print('material name: %r' % material.name)
                material_list.append(material)

                # MATERIAL EFFECT
                effect_name = material.scs_props.mat_effect_name

                # PRESET SHADERS
                flags = 0
                def_cnt = attribute_cnt = texture_cnt = 0
                def_sections = []
                attribute_sections = []
                texture_sections = []
                active_shader_preset_name = material.scs_props.active_shader_preset_name

                # SUBSTANCE
                substance_value = material.scs_props.substance
                # only write substance to material if it's assigned
                if substance_value != "None" and substance_value != "":

                    substance_data = _SectionData("Attribute")
                    substance_data.props.append(("Format", "STRING"))
                    substance_data.props.append(("Tag", "substance"))
                    substance_data.props.append(("Value", ["i", (substance_value,)]))
                    attribute_sections.append(substance_data)
                    attribute_cnt += 1

                if active_shader_preset_name in _get_shader_presets_inventory() and active_shader_preset_name != "<none>":

                    preset = _get_shader_presets_inventory()[active_shader_preset_name]
                    flavors_str = effect_name[len(preset.effect):]
                    section = _shader_presets_cache.get_section(preset, flavors_str)

                    # FLAGS
                    for prop in section.props:

                        if prop[0] == "Flags":
                            flags = int(not material.scs_props.enable_aliasing)
                            break

                    # COLLECT ATTRIBUTES AND TEXTURES
                    for item in section.sections:

                        # DATA EXCHANGE FORMAT ATRIBUTE
                        if item.type == "DataExchangeFormat":
                            def_data = _SectionData("DataExchangeFormat")
                            for rec in item.props:
                                def_data.props.append((rec[0], rec[1]))
                            def_sections.append(def_data)
                            def_cnt += 1

                        # if attribute is hidden in shader preset ignore it on export
                        # this is useful for flavor hiding some attributes from original material
                        # eg: airbrush on "truckpaint" hides R G B aux attributes which are not present
                        # when using airbrush flavor
                        hidden = item.get_prop_value("Hide")
                        if hidden and hidden == "True":
                            continue

                        preview_only = item.get_prop_value("PreviewOnly")
                        if preview_only and preview_only == "True":
                            continue

                        # ATTRIBUTES
                        if item.type == "Attribute":
                            # print('     Attribute:')

                            attribute_data = _SectionData("Attribute")
                            for rec in item.props:
                                # print('       rec: %r' % str(rec))
                                if rec[0] == "Format":
                                    attribute_data.props.append((rec[0], rec[1]))
                                elif rec[0] == "Tag":
                                    # tag_prop = rec[1].replace("[", "").replace("]", "")
                                    # attribute_data.props.append((rec[0], tag_prop))
                                    attribute_data.props.append((rec[0], rec[1]))
                                elif rec[0] == "Value":
                                    format_prop = item.get_prop("Format")[1]
                                    tag_prop = item.get_prop("Tag")[1]
                                    tag_prop = tag_prop.replace("[", "").replace("]", "")
                                    # print('         format_prop: %r' % str(format_prop))
                                    # print('         tag_prop: %r' % str(tag_prop))
                                    if "aux" in tag_prop:
                                        aux_props = getattr(material.scs_props, "shader_attribute_" + tag_prop)
                                        value = []
                                        for aux_prop in aux_props:
                                            value.append(aux_prop.value)

                                        # extract list if there is only one value inside and tagged as FLOAT
                                        # otherwise it gets saved as: "Value: ( [0.0] )" instead of: "Value: ( 0.0 )"
                                        if len(value) == 1 and format_prop == "FLOAT":
                                            value = value[0]

                                    else:
                                        value = getattr(material.scs_props, "shader_attribute_" + tag_prop, "NO TAG")
                                    # print('         value: %s' % str(value))
                                    if format_prop == 'FLOAT':
                                        attribute_data.props.append((rec[0], ["&&", (value,)]))
                                    else:
                                        attribute_data.props.append((rec[0], ["i", tuple(value)]))
                            attribute_sections.append(attribute_data)
                            attribute_cnt += 1

                        # TEXTURES
                        elif item.type == "Texture":
                            # print('     Texture:')

                            texture_data = _SectionData("Texture")
                            for rec in item.props:
                                # print('       rec: %r' % str(rec))
                                if rec[0] == "Tag":
                                    tag_prop = rec[1].split(":")[1]
                                    tag = str("texture[" + str(texture_cnt) + "]:" + tag_prop)
                                    texture_data.props.append((rec[0], tag))
                                elif rec[0] == "Value":
                                    tag_prop = item.get_prop("Tag")[1].split(":")[1]
                                    # print('         tag_prop: %r' % str(tag_prop))

                                    # create and get path to tobj
                                    tobj_rel_path = _get_texture_path_from_material(material, tag_prop,
                                                                                    os.path.dirname(filepath))

                                    texture_data.props.append((rec[0], tobj_rel_path))

                            texture_sections.append(texture_data)
                            texture_cnt += 1

                    material_export_data = _SectionData("Material")
                    material_export_data.props.append(("Alias", material.name))
                    material_export_data.props.append(("Effect", effect_name))
                    material_export_data.props.append(("Flags", flags))
                    if output_type.startswith('def'):
                        material_export_data.props.append(("DataExchangeFormatCount", def_cnt))
                    material_export_data.props.append(("AttributeCount", attribute_cnt))
                    material_export_data.props.append(("TextureCount", texture_cnt))
                    if output_type.startswith('def'):
                        for def_section in def_sections:
                            material_export_data.sections.append(def_section)
                    for attribute in attribute_sections:
                        material_export_data.sections.append(attribute)
                    for texture in texture_sections:
                        material_export_data.sections.append(texture)

                elif active_shader_preset_name == "<imported>":

                    material_attributes = material['scs_shader_attributes']['attributes'].to_dict().values()
                    material_textures = material['scs_shader_attributes']['textures'].to_dict().values()

                    material_export_data = _SectionData("Material")
                    material_export_data.props.append(("Alias", material.name))
                    material_export_data.props.append(("Effect", effect_name))
                    material_export_data.props.append(("Flags", int(not material.scs_props.enable_aliasing)))
                    material_export_data.props.append(("AttributeCount", len(material_attributes)))
                    material_export_data.props.append(("TextureCount", len(material_textures)))

                    for attribute_dict in material_attributes:
                        attribute_section = _SectionData("Attribute")

                        format_value = ""
                        for attr_prop in sorted(attribute_dict.keys()):

                            # get the format of current attribute (we assume that "Format" attribute is before "Value" attribute in this for loop)
                            if attr_prop == "Format":
                                format_value = attribute_dict[attr_prop]

                            if attr_prop == "Value" and ("FLOAT" in format_value or "STRING" in format_value):

                                tag_prop = attribute_dict["Tag"].replace("[", "").replace("]", "")
                                if "aux" in tag_prop:
                                    aux_props = getattr(material.scs_props, "shader_attribute_" + tag_prop)
                                    value = []
                                    for aux_prop in aux_props:
                                        value.append(aux_prop.value)
                                else:
                                    value = getattr(material.scs_props, "shader_attribute_" + tag_prop, None)
                                    if isinstance(value, float):
                                        value = [value]

                                if value is None:
                                    attribute_section.props.append((attr_prop, ["i", tuple(attribute_dict[attr_prop])]))
                                else:
                                    attribute_section.props.append((attr_prop, ["i", tuple(value)]))

                            elif attr_prop == "Tag" and "aux" in attribute_dict[attr_prop]:
                                attribute_section.props.append((attr_prop, "aux[" + attribute_dict[attr_prop][3:] + "]"))
                            else:
                                attribute_section.props.append((attr_prop, attribute_dict[attr_prop]))

                        material_export_data.sections.append(attribute_section)

                    for texture_dict in material_textures:
                        texture_section = _SectionData("Texture")

                        tag_id_string = ""
                        for tex_prop in sorted(texture_dict.keys()):

                            if tex_prop == "Tag":
                                tag_id_string = texture_dict[tex_prop].split(':')[1]

                            if tex_prop == "Value" and tag_id_string != "":

                                tobj_rel_path = _get_texture_path_from_material(material, tag_id_string, os.path.dirname(filepath))
                                texture_section.props.append((tex_prop, tobj_rel_path))

                            else:
                                texture_section.props.append((tex_prop, texture_dict[tex_prop]))

                        material_export_data.sections.append(texture_section)

                else:
                    # DEFAULT MATERIAL
                    material_name = str("_" + material_name + "_-_default_settings_")
                    material_export_data = _default_material(material_name)

            material_dict[material_name] = material_export_data

        # create materials sections for looks
        material_sections = _fill_material_sections(material_list, material_dict)
        look_data = {
            "name": curr_look_name,
            "material_sections": material_sections
        }
        look_list.append(look_data)

    # restore look applied before export
    root_object.scs_props.active_scs_look = saved_active_look

    # PARTS AND VARIANTS...
    used_parts_names = used_parts.get_as_list()
    part_list_cnt = len(used_parts_names)
    if len(root_object.scs_object_variant_inventory) == 0:
        # If there is no Variant, add the Default one...
        part_list = _fill_part_list(root_object.scs_object_part_inventory, used_parts_names, all_parts=True)
        variant_list.append((_VARIANT_consts.default_name, part_list), )
    else:
        for variant in root_object.scs_object_variant_inventory:
            part_list = _fill_part_list(variant.parts, used_parts_names)
            variant_list.append((variant.name, part_list), )

    # DATA CREATION
    header_section = _fill_header_section(file_name, scs_globals.sign_export)
    look_section = _fill_look_sections(look_list)
    # part_sections = fill_part_section(part_list)
    variant_section = _fill_variant_sections(variant_list)
    comment_header_section = _fill_comment_header_section(look_list, variant_list)
    global_section = _fill_global_section(len(look_list), len(variant_list), part_list_cnt, len(used_materials_pairs))

    # DATA ASSEMBLING
    pit_container = [comment_header_section, header_section, global_section]
    for section in look_section:
        pit_container.append(section)
    for section in variant_section:
        pit_container.append(section)

    # FILE EXPORT
    ind = "    "
    pit_filepath = str(filepath + ".pit")
    result = _pix_container.write_data_to_file(pit_container, pit_filepath, ind)

    # print("************************************")
    return result
Beispiel #11
0
def export(root_object, filepath, used_materials, used_parts):
    """Export PIT.

    :param root_object: SCS root object
    :type root_object: bpy.types.Object
    :param filepath: PIT file path
    :type filepath: str
    :param used_materials: materials transitional structure for accessing stored materials from PIM
    :type used_materials: io_scs_tools.exp.transition_structs.materials.MaterialsTrans
    :param used_parts: parts transitional structure for accessing stored parts from PIM, PIC and PIP
    :type used_parts: io_scs_tools.exp.transition_structs.parts.PartsTrans
    :return: True if successful; False otherwise;
    :rtype: bool
    """

    scs_globals = _get_scs_globals()
    output_type = scs_globals.output_type

    file_name = root_object.name

    print("\n************************************")
    print("**      SCS PIT Exporter          **")
    print("**      (c)2014 SCS Software      **")
    print("************************************\n")

    # DATA GATHERING
    look_list = []
    variant_list = []

    saved_active_look = root_object.scs_props.active_scs_look
    looks_inventory = root_object.scs_object_look_inventory
    looks_count = len(looks_inventory)
    if looks_count <= 0:
        looks_count = 1

    used_materials_pairs = used_materials.get_as_pairs()
    for i in range(0, looks_count):

        # apply each look from inventory first
        if len(looks_inventory) > 0:
            root_object.scs_props.active_scs_look = i

            # actually write values to material because Blender might not refresh data yet
            _looks.apply_active_look(root_object)

            curr_look_name = looks_inventory[i].name
        else:  # if no looks create default
            curr_look_name = "default"

        material_dict = {}
        material_list = []
        # get materials data
        for material_name, material in used_materials_pairs:
            if material is None:
                material_name = str("_default_material_-_default_settings_")

                # DEFAULT MATERIAL
                material_export_data = _default_material(material_name)
                material_list.append(material_name)

            else:
                # print('material name: %r' % material.name)
                material_list.append(material)

                # MATERIAL EFFECT
                effect_name = material.scs_props.mat_effect_name

                # PRESET SHADERS
                flags = 0
                def_cnt = attribute_cnt = texture_cnt = 0
                def_sections = []
                attribute_sections = []
                texture_sections = []
                active_shader_preset_name = material.scs_props.active_shader_preset_name

                # SUBSTANCE
                substance_value = material.scs_props.substance
                # only write substance to material if it's assigned
                if substance_value != "None" and substance_value != "":

                    substance_data = _SectionData("Attribute")
                    substance_data.props.append(("Format", "STRING"))
                    substance_data.props.append(("Tag", "substance"))
                    substance_data.props.append(
                        ("Value", ["i", (substance_value, )]))
                    attribute_sections.append(substance_data)
                    attribute_cnt += 1

                if active_shader_preset_name in _get_shader_presets_inventory(
                ) and active_shader_preset_name != "<none>":

                    preset = _get_shader_presets_inventory(
                    )[active_shader_preset_name]
                    flavors_str = effect_name[len(preset.effect):]
                    section = _shader_presets_cache.get_section(
                        preset, flavors_str)

                    # FLAGS
                    for prop in section.props:

                        if prop[0] == "Flags":
                            flags = int(not material.scs_props.enable_aliasing)
                            break

                    # COLLECT ATTRIBUTES AND TEXTURES
                    for item in section.sections:

                        # DATA EXCHANGE FORMAT ATRIBUTE
                        if item.type == "DataExchangeFormat":
                            def_data = _SectionData("DataExchangeFormat")
                            for rec in item.props:
                                def_data.props.append((rec[0], rec[1]))
                            def_sections.append(def_data)
                            def_cnt += 1

                        # if attribute is hidden in shader preset ignore it on export
                        # this is useful for flavor hiding some attributes from original material
                        # eg: airbrush on "truckpaint" hides R G B aux attributes which are not present
                        # when using airbrush flavor
                        hidden = item.get_prop_value("Hide")
                        if hidden and hidden == "True":
                            continue

                        preview_only = item.get_prop_value("PreviewOnly")
                        if preview_only and preview_only == "True":
                            continue

                        # ATTRIBUTES
                        if item.type == "Attribute":
                            # print('     Attribute:')

                            attribute_data = _SectionData("Attribute")
                            for rec in item.props:
                                # print('       rec: %r' % str(rec))
                                if rec[0] == "Format":
                                    attribute_data.props.append(
                                        (rec[0], rec[1]))
                                elif rec[0] == "Tag":
                                    # tag_prop = rec[1].replace("[", "").replace("]", "")
                                    # attribute_data.props.append((rec[0], tag_prop))
                                    attribute_data.props.append(
                                        (rec[0], rec[1]))
                                elif rec[0] == "Value":
                                    format_prop = item.get_prop("Format")[1]
                                    tag_prop = item.get_prop("Tag")[1]
                                    tag_prop = tag_prop.replace("[",
                                                                "").replace(
                                                                    "]", "")
                                    # print('         format_prop: %r' % str(format_prop))
                                    # print('         tag_prop: %r' % str(tag_prop))
                                    if "aux" in tag_prop:
                                        aux_props = getattr(
                                            material.scs_props,
                                            "shader_attribute_" + tag_prop)
                                        value = []
                                        for aux_prop in aux_props:
                                            value.append(aux_prop.value)

                                        # extract list if there is only one value inside and tagged as FLOAT
                                        # otherwise it gets saved as: "Value: ( [0.0] )" instead of: "Value: ( 0.0 )"
                                        if len(
                                                value
                                        ) == 1 and format_prop == "FLOAT":
                                            value = value[0]

                                    else:
                                        value = getattr(
                                            material.scs_props,
                                            "shader_attribute_" + tag_prop,
                                            "NO TAG")
                                    # print('         value: %s' % str(value))
                                    if format_prop == 'FLOAT':
                                        attribute_data.props.append(
                                            (rec[0], ["&&", (value, )]))
                                    else:
                                        attribute_data.props.append(
                                            (rec[0], ["i", tuple(value)]))
                            attribute_sections.append(attribute_data)
                            attribute_cnt += 1

                        # TEXTURES
                        elif item.type == "Texture":
                            # print('     Texture:')

                            texture_data = _SectionData("Texture")
                            for rec in item.props:
                                # print('       rec: %r' % str(rec))
                                if rec[0] == "Tag":
                                    tag_prop = rec[1].split(":")[1]
                                    tag = str("texture[" + str(texture_cnt) +
                                              "]:" + tag_prop)
                                    texture_data.props.append((rec[0], tag))
                                elif rec[0] == "Value":
                                    tag_prop = item.get_prop("Tag")[1].split(
                                        ":")[1]
                                    # print('         tag_prop: %r' % str(tag_prop))

                                    # create and get path to tobj
                                    tobj_rel_path = _get_texture_path_from_material(
                                        material, tag_prop,
                                        os.path.dirname(filepath))

                                    texture_data.props.append(
                                        (rec[0], tobj_rel_path))

                            texture_sections.append(texture_data)
                            texture_cnt += 1

                    material_export_data = _SectionData("Material")
                    material_export_data.props.append(("Alias", material.name))
                    material_export_data.props.append(("Effect", effect_name))
                    material_export_data.props.append(("Flags", flags))
                    if output_type.startswith('def'):
                        material_export_data.props.append(
                            ("DataExchangeFormatCount", def_cnt))
                    material_export_data.props.append(
                        ("AttributeCount", attribute_cnt))
                    material_export_data.props.append(
                        ("TextureCount", texture_cnt))
                    if output_type.startswith('def'):
                        for def_section in def_sections:
                            material_export_data.sections.append(def_section)
                    for attribute in attribute_sections:
                        material_export_data.sections.append(attribute)
                    for texture in texture_sections:
                        material_export_data.sections.append(texture)

                elif active_shader_preset_name == "<imported>":

                    material_attributes = material['scs_shader_attributes'][
                        'attributes'].to_dict().values()
                    material_textures = material['scs_shader_attributes'][
                        'textures'].to_dict().values()

                    material_export_data = _SectionData("Material")
                    material_export_data.props.append(("Alias", material.name))
                    material_export_data.props.append(("Effect", effect_name))
                    material_export_data.props.append(
                        ("Flags", int(not material.scs_props.enable_aliasing)))
                    material_export_data.props.append(
                        ("AttributeCount", len(material_attributes)))
                    material_export_data.props.append(
                        ("TextureCount", len(material_textures)))

                    for attribute_dict in material_attributes:
                        attribute_section = _SectionData("Attribute")

                        format_value = ""
                        for attr_prop in sorted(attribute_dict.keys()):

                            # get the format of current attribute (we assume that "Format" attribute is before "Value" attribute in this for loop)
                            if attr_prop == "Format":
                                format_value = attribute_dict[attr_prop]

                            if attr_prop == "Value" and (
                                    "FLOAT" in format_value
                                    or "STRING" in format_value):

                                tag_prop = attribute_dict["Tag"].replace(
                                    "[", "").replace("]", "")
                                if "aux" in tag_prop:
                                    aux_props = getattr(
                                        material.scs_props,
                                        "shader_attribute_" + tag_prop)
                                    value = []
                                    for aux_prop in aux_props:
                                        value.append(aux_prop.value)
                                else:
                                    value = getattr(
                                        material.scs_props,
                                        "shader_attribute_" + tag_prop, None)
                                    if isinstance(value, float):
                                        value = [value]

                                if value is None:
                                    attribute_section.props.append(
                                        (attr_prop, [
                                            "i",
                                            tuple(attribute_dict[attr_prop])
                                        ]))
                                else:
                                    attribute_section.props.append(
                                        (attr_prop, ["i", tuple(value)]))

                            elif attr_prop == "Tag" and "aux" in attribute_dict[
                                    attr_prop]:
                                attribute_section.props.append(
                                    (attr_prop, "aux[" +
                                     attribute_dict[attr_prop][3:] + "]"))
                            else:
                                attribute_section.props.append(
                                    (attr_prop, attribute_dict[attr_prop]))

                        material_export_data.sections.append(attribute_section)

                    for texture_dict in material_textures:
                        texture_section = _SectionData("Texture")

                        tag_id_string = ""
                        for tex_prop in sorted(texture_dict.keys()):

                            if tex_prop == "Tag":
                                tag_id_string = texture_dict[tex_prop].split(
                                    ':')[1]

                            if tex_prop == "Value" and tag_id_string != "":

                                tobj_rel_path = _get_texture_path_from_material(
                                    material, tag_id_string,
                                    os.path.dirname(filepath))
                                texture_section.props.append(
                                    (tex_prop, tobj_rel_path))

                            else:
                                texture_section.props.append(
                                    (tex_prop, texture_dict[tex_prop]))

                        material_export_data.sections.append(texture_section)

                else:
                    # DEFAULT MATERIAL
                    material_name = str("_" + material_name +
                                        "_-_default_settings_")
                    material_export_data = _default_material(material_name)

            material_dict[material_name] = material_export_data

        # create materials sections for looks
        material_sections = _fill_material_sections(material_list,
                                                    material_dict)
        look_data = {
            "name": curr_look_name,
            "material_sections": material_sections
        }
        look_list.append(look_data)

    # restore look applied before export
    root_object.scs_props.active_scs_look = saved_active_look

    # PARTS AND VARIANTS...
    used_parts_names = used_parts.get_as_list()
    part_list_cnt = len(used_parts_names)
    if len(root_object.scs_object_variant_inventory) == 0:
        # If there is no Variant, add the Default one...
        part_list = _fill_part_list(root_object.scs_object_part_inventory,
                                    used_parts_names,
                                    all_parts=True)
        variant_list.append((_VARIANT_consts.default_name, part_list), )
    else:
        for variant in root_object.scs_object_variant_inventory:
            part_list = _fill_part_list(variant.parts, used_parts_names)
            variant_list.append((variant.name, part_list), )

    # DATA CREATION
    header_section = _fill_header_section(file_name, scs_globals.sign_export)
    look_section = _fill_look_sections(look_list)
    # part_sections = fill_part_section(part_list)
    variant_section = _fill_variant_sections(variant_list)
    comment_header_section = _fill_comment_header_section(
        look_list, variant_list)
    global_section = _fill_global_section(len(look_list), len(variant_list),
                                          part_list_cnt,
                                          len(used_materials_pairs))

    # DATA ASSEMBLING
    pit_container = [comment_header_section, header_section, global_section]
    for section in look_section:
        pit_container.append(section)
    for section in variant_section:
        pit_container.append(section)

    # FILE EXPORT
    ind = "    "
    pit_filepath = str(filepath + ".pit")
    result = _pix_container.write_data_to_file(pit_container, pit_filepath,
                                               ind)

    # print("************************************")
    return result
Beispiel #12
0
 def shader_presets_filepath_update(self, context):
     # print('Shader Presets Library Path UPDATE: "%s"' % self.shader_presets_filepath)
     _config_container.update_shader_presets_path(
         _get_shader_presets_inventory(), self.shader_presets_filepath)
     return None
Beispiel #13
0
def post_load(scene):
    # get Blender Tools version from last blend file load
    last_load_bt_ver = _get_scs_globals().last_load_bt_version

    scs_roots = None

    """
    Applies fixes for v0.6 or less:
    1. fixes reflection textures tga's for tobjs as TOBJ load is now supported and unlock that textures
    2. calls update on all set textures to correct paths for them
    3. tries to fix active shader preset name for materials, because of new flavor system
    """
    if _info_utils.cmp_ver_str(last_load_bt_ver, "0.6") <= 0:

        print("INFO\t-  Applying fixes for version <= 0.6")

        for material in bpy.data.materials:

            # ignore materials not related to blender tools
            if material.scs_props.mat_effect_name == "":
                continue

            for tex_type in material.scs_props.get_texture_types().keys():

                texture_attr_str = "shader_texture_" + tex_type
                if texture_attr_str in material.scs_props.keys():

                    # 1. fix reflection textures
                    if tex_type == "reflection":

                        is_building_ref = material.scs_props[texture_attr_str].endswith("/bulding_ref.tga")
                        is_generic_s = material.scs_props[texture_attr_str].endswith("material/environment/generic_s.tga")
                        is_glass_interior = material.scs_props.active_shader_preset_name == "glass - interior"
                        is_dif_spec_weight_add_env = material.scs_props.active_shader_preset_name == "dif.spec.weight.add.env"
                        is_truckpaint = material.scs_props.active_shader_preset_name.startswith("truckpaint")

                        # fix paths
                        if is_building_ref:
                            material.scs_props[texture_attr_str] = material.scs_props[texture_attr_str][:-4]
                            material.scs_props[texture_attr_str + "_locked"] = False
                        elif is_generic_s:
                            if is_glass_interior:
                                material.scs_props[texture_attr_str] = "//material/environment/interior_reflection"
                            elif is_dif_spec_weight_add_env:
                                material.scs_props[texture_attr_str] = "//material/environment/generic_reflection"
                            else:
                                material.scs_props[texture_attr_str] = "//material/environment/vehicle_reflection"

                            # unlock reflection textures everywhere except on truckpaint shader
                            if not is_truckpaint:
                                material.scs_props[texture_attr_str + "_locked"] = False

                        # acquire roots on demand only once
                        scs_roots = _object_utils.gather_scs_roots(bpy.data.objects) if not scs_roots else scs_roots

                        # propagate reflection texture change on all of the looks.
                        # NOTE: We can afford write through because old BT had all reflection textures locked
                        # meaning user had to use same texture on all looks
                        # NOTE#2: Printouts like:
                        # "Look with ID: X doesn't have entry for material 'X' in SCS Root 'X',
                        #  property 'shader_texture_reflection' won't be updated!"
                        # are expected here, because we don't use any safety check,
                        # if material is used on the mesh objects inside scs root
                        for scs_root in scs_roots:
                            _looks.write_through(scs_root, material, texture_attr_str)

                    # 2. trigger update function for path reload and reload of possible missing textures
                    update_func = getattr(material.scs_props, "update_" + texture_attr_str, None)
                    if update_func:
                        update_func(material)

            # ignore already properly set materials
            if material.scs_props.active_shader_preset_name in _get_shader_presets_inventory():
                continue

            # 3. try to recover "active_shader_preset_name" from none flavor times Blender Tools
            material_textures = {}
            if "scs_shader_attributes" in material and "textures" in material["scs_shader_attributes"]:
                for texture in material["scs_shader_attributes"]["textures"].values():
                    tex_id = texture["Tag"].split(":")[1]
                    tex_value = texture["Value"]
                    material_textures[tex_id] = tex_value

            (preset_name, preset_section) = _material_utils.find_preset(material.scs_props.mat_effect_name, material_textures)
            if preset_name:
                material.scs_props.active_shader_preset_name = preset_name

                # acquire roots on demand only once
                scs_roots = _object_utils.gather_scs_roots(bpy.data.objects) if not scs_roots else scs_roots

                # make sure to fix active preset shader name in all looks
                # NOTE: Printouts like:
                # "Look with ID: X doesn't have entry for material 'X' in SCS Root 'X',
                #  property 'active_shader_preset_name' won't be updated!"
                # are expected here, because we don't use any safety check,
                # if material is used on the mesh objects inside scs root
                for scs_root in scs_roots:
                    _looks.write_through(scs_root, material, "active_shader_preset_name")

    # as last update "last load" Blender Tools version to current
    _get_scs_globals().last_load_bt_version = get_tools_version()