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 name_update(self, context):

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

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

        # always get scs root because we allow editing of parts in any child
        scs_root_obj = _object_utils.get_scs_root(context.active_object)

        # if there is more of parts with same name, make postfixed name (this will cause another name update)
        if len(
                _inventory.get_indices(scs_root_obj.scs_object_part_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_part_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

        if "scs_part_old_name" in self:

            if scs_root_obj:

                # fix part name in all children of current root
                children = _object_utils.get_children(scs_root_obj)
                for child in children:

                    # fix part name in child with existing old name
                    if child.scs_props.scs_part == self["scs_part_old_name"]:

                        child.scs_props.scs_part = self.name

                # rename parts in all variants also
                variant_inventory = scs_root_obj.scs_object_variant_inventory
                for variant in variant_inventory:
                    for part in variant.parts:

                        if part.name == self["scs_part_old_name"]:
                            part.name = self.name
                            break

        # backup current name for checking children on next renaming
        self["scs_part_old_name"] = self.name
Example #3
0
    def name_update(self, context):

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

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

        # always get scs root because we allow editing of parts in any child
        scs_root_obj = _object_utils.get_scs_root(context.active_object)

        # if there is more of parts with same name, make postfixed name (this will cause another name update)
        if len(_inventory.get_indices(scs_root_obj.scs_object_part_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_part_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

        if "scs_part_old_name" in self:

            if scs_root_obj:

                # fix part name in all children of current root
                children = _object_utils.get_children(scs_root_obj)
                for child in children:

                    # fix part name in child with existing old name
                    if child.scs_props.scs_part == self["scs_part_old_name"]:

                        child.scs_props.scs_part = self.name

                # rename parts in all variants also
                variant_inventory = scs_root_obj.scs_object_variant_inventory
                for variant in variant_inventory:
                    for part in variant.parts:

                        if part.name == self["scs_part_old_name"]:
                            part.name = self.name
                            break

        # backup current name for checking children on next renaming
        self["scs_part_old_name"] = self.name
Example #4
0
        def update_name(self, context):
            __update_look__(self, context)

            if hasattr(context, "active_object") and hasattr(context.active_object, "active_material"):
                material = context.active_object.active_material
                if material:

                    custom_maps = material.scs_props.custom_tex_coord_maps
                    # force prescribed pattern for name ("tex_coord_X" where X is unsigned integer) and avoid duplicates
                    if not re.match("\Atex_coord_\d+\Z", self.name) or len(_inventory.get_indices(custom_maps, self.name)) == 2:
                        i = 0
                        new_name = "tex_coord_" + str(i)
                        while _inventory.get_index(custom_maps, new_name) != -1:
                            i += 1
                            new_name = "tex_coord_" + str(i)

                        if self.name != new_name:
                            self.name = new_name
Example #5
0
        def update_name(self, context):

            if hasattr(context, "active_object") and hasattr(
                    context.active_object, "active_material"):
                material = context.active_object.active_material
                if material:

                    custom_maps = material.scs_props.shader_custom_tex_coord_maps
                    # force prescribed pattern for name ("tex_coord_X" where X is unsigned integer) and avoid duplicates
                    if not re.match("\Atex_coord_\d+\Z", self.name) or len(
                            _inventory.get_indices(custom_maps,
                                                   self.name)) == 2:
                        i = 0
                        new_name = "tex_coord_" + str(i)
                        while _inventory.get_index(custom_maps,
                                                   new_name) != -1:
                            i += 1
                            new_name = "tex_coord_" + str(i)

                        if self.name != new_name:
                            self.name = new_name
Example #6
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 #7
0
    def active_scs_part_get(self):
        """Getting active index in SCS Parts list. On active object change active index of the list is altered
        with the index of part belonging to new active object.

        """

        if not "active_scs_part_old_active" in self:
            self["active_scs_part_old_active"] = ""

        if not "active_scs_part_value" in self:
            self["active_scs_part_value"] = 0

        scs_root_object = _object_utils.get_scs_root(bpy.context.active_object)
        if scs_root_object and bpy.context.active_object != scs_root_object:

            # if old active object is different than current
            # set the value for active part index from it
            if self["active_scs_part_old_active"] != bpy.context.active_object.name:
                self["active_scs_part_value"] = _inventory.get_index(scs_root_object.scs_object_part_inventory,
                                                                     bpy.context.active_object.scs_props.scs_part)

        self["active_scs_part_old_active"] = bpy.context.active_object.name
        return self["active_scs_part_value"]
Example #8
0
def set_shader_data_to_material(material, section, is_import=False, override_back_data=True):
    """Used to set up material properties from given shader data even via UI or on import.

    :param material: blender material to which section data should be set
    :type material: bpy.types.Material
    :param section: new material data presented with Material section of PIX files
    :type section: io_scs_tools.internals.structure.SectionData
    :param is_import: flag indication if shader data are set from import process
    :type is_import: bool
    :param override_back_data: flag indication if back data for UI shall be overwritten
    :type override_back_data: bool
    """

    preset_effect = section.get_prop_value("Effect")

    # check shader flags
    for attr in section.props:

        if attr[0] == "Flags":
            material.scs_props.enable_aliasing = not attr[1] == 1  # Flags: 1 #DISABLE ALIASING
            break

    attributes = {}
    textures = {}
    attribute_i = 0
    texture_i = 0
    used_attribute_types = {}  # attribute types used by current shader
    used_texture_types = {}  # texture types used by current shader and should be overlooked during clearing of texture slots
    for item in section.sections:

        if item.type == "Attribute":
            attribute_data = {}
            for prop in item.props:
                key, value = prop

                # # GETTING RID OF "[" AND "]" CHARS...
                if type(value) is str:
                    value = value.replace("[", "").replace("]", "")

                attribute_data[key] = value

            attribute_type = attribute_data['Tag']

            attributes[str(attribute_i)] = attribute_data
            attribute_i += 1

            used_attribute_types[attribute_type] = attribute_data

        elif item.type == "Texture":
            texture_data = {}
            for prop in item.props:
                # print('      prop: "%s"' % str(prop))
                texture_data[prop[0]] = prop[1]

            # APPLY SECTION TEXTURE VALUES
            texture_type = texture_data['Tag'].split(':')[1]
            tex_type = texture_type[8:]

            used_texture_types[tex_type] = texture_data

            textures[str(texture_i)] = texture_data
            texture_i += 1

    scs_props_keys = material.scs_props.keys()
    # if overriding back data also make sure to clear attribute values for current shader
    # to prevent storing of unused values from blend data block
    # NOTE: looks also takes into account that all the unused properties are omitted from scs_props dict
    if override_back_data:
        for key in scs_props_keys:
            is_key_used = False
            if key.startswith("shader_attribute"):
                for used_attribute in used_attribute_types:
                    if used_attribute in key[16:]:
                        is_key_used = True

            if key.startswith("shader_texture"):
                for used_tex_type in used_texture_types:
                    if used_tex_type in key[14:]:
                        is_key_used = True

            # delete only unused shader keys everything else should stay in the place
            # as those keys might be used in some other way
            if not is_key_used and key.startswith("shader_"):
                lprint("D Unsetting property from material in set_shader_data %s:", (key,))
                material.scs_props.property_unset(key)

    # apply used attributes
    created_attributes = {}
    for attribute_type in used_attribute_types.keys():
        attribute_data = used_attribute_types[attribute_type]

        # acquire old attribute value if exists and not importing
        old_value = None
        if "shader_attribute_" + attribute_type in scs_props_keys and not is_import:
            old_value = getattr(material.scs_props, "shader_attribute_" + attribute_type)

        if attribute_type in ("diffuse", "specular", "env_factor", "fresnel", "tint"):

            if not old_value:
                material.scs_props["shader_attribute_" + attribute_type] = attribute_data['Value']

            created_attributes[attribute_type] = material.scs_props["shader_attribute_" + attribute_type]

        elif attribute_type in ("shininess", "add_ambient", "reflection", "reflection2", "shadow_bias", "tint_opacity"):

            if not old_value:
                material.scs_props["shader_attribute_" + attribute_type] = attribute_data['Value'][0]

            created_attributes[attribute_type] = material.scs_props["shader_attribute_" + attribute_type]

        elif attribute_type.startswith("aux") and hasattr(material.scs_props, "shader_attribute_" + attribute_type):

            auxiliary_prop = getattr(material.scs_props, "shader_attribute_" + attribute_type, None)

            # NOTE : invalidate old value if size of existing auxiliary property is different
            # then size of new one overwrite it anyway, because otherwise we will might access
            # values that doesn't exists but they should, for example:
            # switching from "eut2.dif.spec.weight.mult2" to "eut2.dif.spec.weight.mult2.weight2"
            if len(auxiliary_prop) != len(attribute_data['Value']):
                old_value = None

            if not old_value:

                # clean old values possible left from previous shader
                while len(auxiliary_prop) > 0:
                    auxiliary_prop.remove(0)

                for val in attribute_data['Value']:
                    item = auxiliary_prop.add()
                    item['value'] = val
                    item['aux_type'] = attribute_type

            created_attributes[attribute_type] = material.scs_props["shader_attribute_" + attribute_type]

        elif attribute_type == "substance":

            if not old_value:
                material.scs_props.substance = attribute_data['Value'][0]

    # if shader attribute properties are still unset reset it to default
    if material.scs_props.substance == _MAT_consts.unset_substance and "substance" not in material.scs_props.keys():
        material.scs_props.substance = "None"

    # collect old uv mappings per tex_coord values and delete them from material (they will be set back later)
    # NOTE: we have to create extra iteration for uv mappings collecting
    # as multiple texture types can use same tex coord and we have to make sure
    # to collect them before we apply any texture data back to material.
    old_texture_mappings = {}
    for tex_type in used_texture_types:

        texture_mappings = getattr(material.scs_props, "shader_texture_" + tex_type + "_uv")
        if override_back_data:
            while len(texture_mappings) > 0:

                # save only set uv mapping tex_cord:value pairs
                if texture_mappings[0].value != "":
                    old_texture_mappings[texture_mappings[0].tex_coord] = texture_mappings[0].value

                texture_mappings.remove(0)

    # apply used textures
    created_textures = {}
    created_tex_mappings = []
    for tex_type in used_texture_types:

        # skip unknown texture type
        if tex_type not in material.scs_props.get_texture_types().keys():
            lprint("D Trying to apply unknown texture type to SCS material: %r", (tex_type,))
            continue

        texture_data = used_texture_types[tex_type]

        # always set texture lock attribute
        # important to set it always as some texture might get unlocked in preset and
        # selecting same present again has to unlock that texture
        texture_locked = False
        if "Lock" in texture_data:
            texture_locked = bool(texture_data["Lock"])
        setattr(material.scs_props, "shader_texture_" + tex_type + "_locked", texture_locked)

        texture_mappings = getattr(material.scs_props, "shader_texture_" + tex_type + "_uv")

        # if shader is imported try to create custom tex coord mappings on material
        if material.scs_props.active_shader_preset_name == "<imported>" and "scs_tex_aliases" in material:
            custom_maps = material.scs_props.custom_tex_coord_maps

            for tex_coord_key in sorted(material["scs_tex_aliases"].keys()):

                if _invetory.get_index(custom_maps, "tex_coord_" + tex_coord_key) == -1:
                    new_map = custom_maps.add()
                    new_map.name = "tex_coord_" + tex_coord_key
                    new_map.value = material["scs_tex_aliases"][tex_coord_key]

            # add one mapping field for using it as a preview uv layer in case of imported shader
            mapping = texture_mappings.add()
            mapping.texture_type = tex_type
            mapping.tex_coord = -1

        # if there is an info about mapping in shader use it (in case of imported material this condition will fall!)
        elif "TexCoord" in texture_data:

            for tex_coord_i, tex_coord in enumerate(texture_data['TexCoord']):
                tex_coord = int(tex_coord)

                if tex_coord != -1:
                    mapping = texture_mappings.add()
                    mapping['texture_type'] = tex_type
                    mapping['tex_coord'] = tex_coord

                    # apply uv mappings either from imported data or from old mappings of previous shader
                    if "scs_tex_aliases" in material:  # scs_tex_aliases are present only on import
                        mapping['value'] = material["scs_tex_aliases"][str(tex_coord)]
                        created_tex_mappings.append((tex_type, mapping.value, tex_coord))

                    elif tex_coord in old_texture_mappings:

                        mapping['value'] = old_texture_mappings[tex_coord]
                        created_tex_mappings.append((tex_type, mapping.value, tex_coord))

        # set texture file to current texture
        scs_texture_str = _path.get_scs_texture_str(texture_data['Value'])

        # apply texture path if not empty and not yet set, except if import is going on
        # NOTE: during import bitmap has to be applied even if empty
        # because otherwise texture from previous look might be applied
        if (scs_texture_str != "" and getattr(material.scs_props, "shader_texture_" + tex_type, "") == "") or is_import:
            material.scs_props["shader_texture_" + tex_type] = scs_texture_str
            created_textures[tex_type] = get_texture(scs_texture_str, tex_type)

            if is_import:

                # only if shader is imported then make sure that by default imported values will be used
                if material.scs_props.active_shader_preset_name == "<imported>":
                    setattr(material.scs_props, "shader_texture_" + tex_type + "_use_imported", True)
                    setattr(material.scs_props, "shader_texture_" + tex_type + "_imported_tobj", texture_data['Value'])

        # if property is still unset reset it to empty
        if getattr(material.scs_props, "shader_texture_" + tex_type, "") == _MAT_consts.unset_bitmap_filepath:
            material.scs_props["shader_texture_" + tex_type] = ""
        else:

            final_tex_str = getattr(material.scs_props, "shader_texture_" + tex_type, "")
            created_textures[tex_type] = get_texture(final_tex_str, tex_type)

            if is_import and not override_back_data:

                if created_textures[tex_type] is None:
                    lprint("E Can't find texture nor TOBJ inside SCS Project Base Path: %r", (final_tex_str,))

    # override shader data for identifying used attributes and textures in UI
    if override_back_data:

        shader_data = {'effect': preset_effect,
                       'attributes': attributes,
                       'textures': textures}
        material["scs_shader_attributes"] = shader_data

    # setup nodes for 3D view visualization
    _shader.setup_nodes(material, preset_effect, created_attributes, created_textures, override_back_data)

    # setup uv mappings to nodes later trough dedicated function, so proper validation is made on tex coord bindings
    for mapping_data in created_tex_mappings:

        # data[0] = texture type;
        # data[1] = uv mapping value;
        # data[2] = tex coord value
        _shader.set_uv(material, mapping_data[0], mapping_data[1], mapping_data[2])
Example #9
0
def set_shader_data_to_material(material,
                                section,
                                is_import=False,
                                override_back_data=True):
    """Used to set up material properties from given shader data even via UI or on import.

    :param material: blender material to which section data should be set
    :type material: bpy.types.Material
    :param section: new material data presented with Material section of PIX files
    :type section: io_scs_tools.internals.structure.SectionData
    :param is_import: flag indication if shader data are set from import process
    :type is_import: bool
    :param override_back_data: flag indication if back data for UI shall be overwritten
    :type override_back_data: bool
    """

    preset_effect = section.get_prop_value("Effect")

    # check shader flags
    for attr in section.props:

        if attr[0] == "Flags":
            material.scs_props.enable_aliasing = not attr[
                1] == 1  # Flags: 1 #DISABLE ALIASING
            break

    attributes = {}
    textures = {}
    attribute_i = 0
    texture_i = 0
    used_attribute_types = {}  # attribute types used by current shader
    used_texture_types = {
    }  # texture types used by current shader and should be overlooked during clearing of texture slots
    for item in section.sections:

        if item.type == "Attribute":
            attribute_data = {}
            for prop in item.props:
                key, value = prop

                # # GETTING RID OF "[" AND "]" CHARS...
                if type(value) is str:
                    value = value.replace("[", "").replace("]", "")

                attribute_data[key] = value

            attribute_type = attribute_data['Tag']

            attributes[str(attribute_i)] = attribute_data
            attribute_i += 1

            used_attribute_types[attribute_type] = attribute_data

        elif item.type == "Texture":
            texture_data = {}
            for prop in item.props:
                # print('      prop: "%s"' % str(prop))
                texture_data[prop[0]] = prop[1]

            # APPLY SECTION TEXTURE VALUES
            texture_type = texture_data['Tag'].split(':')[1]
            tex_type = texture_type[8:]

            used_texture_types[tex_type] = texture_data

            textures[str(texture_i)] = texture_data
            texture_i += 1

    scs_props_keys = material.scs_props.keys()
    # if overriding back data also make sure to clear attribute values for current shader
    # to prevent storing of unused values from blend data block
    # NOTE: looks also takes into account that all the unused properties are omitted from scs_props dict
    if override_back_data:
        for key in scs_props_keys:
            is_key_used = False
            if key.startswith("shader_attribute"):
                for used_attribute in used_attribute_types:
                    if used_attribute in key[16:]:
                        is_key_used = True

            if key.startswith("shader_texture"):
                for used_tex_type in used_texture_types:
                    if used_tex_type in key[14:]:
                        is_key_used = True

            # delete only unused shader keys everything else should stay in the place
            # as those keys might be used in some other way
            if not is_key_used and key.startswith("shader_"):
                lprint(
                    "D Unsetting property from material in set_shader_data %s:",
                    (key, ))
                material.scs_props.property_unset(key)

    # apply used attributes
    created_attributes = {}
    for attribute_type in used_attribute_types.keys():
        attribute_data = used_attribute_types[attribute_type]

        # acquire old attribute value if exists and not importing
        old_value = None
        if "shader_attribute_" + attribute_type in scs_props_keys and not is_import:
            old_value = getattr(material.scs_props,
                                "shader_attribute_" + attribute_type)

        if attribute_type in ("diffuse", "specular", "env_factor", "fresnel",
                              "tint"):

            if not old_value:
                material.scs_props["shader_attribute_" +
                                   attribute_type] = attribute_data['Value']

            created_attributes[attribute_type] = material.scs_props[
                "shader_attribute_" + attribute_type]

        elif attribute_type in ("shininess", "add_ambient", "reflection",
                                "reflection2", "shadow_bias", "tint_opacity"):

            if not old_value:
                material.scs_props["shader_attribute_" +
                                   attribute_type] = attribute_data['Value'][0]

            created_attributes[attribute_type] = material.scs_props[
                "shader_attribute_" + attribute_type]

        elif attribute_type.startswith("aux") and hasattr(
                material.scs_props, "shader_attribute_" + attribute_type):

            auxiliary_prop = getattr(material.scs_props,
                                     "shader_attribute_" + attribute_type,
                                     None)

            # NOTE : invalidate old value if size of existing auxiliary property is different
            # then size of new one overwrite it anyway, because otherwise we will might access
            # values that doesn't exists but they should, for example:
            # switching from "eut2.dif.spec.weight.mult2" to "eut2.dif.spec.weight.mult2.weight2"
            if len(auxiliary_prop) != len(attribute_data['Value']):
                old_value = None

            if not old_value:

                # clean old values possible left from previous shader
                while len(auxiliary_prop) > 0:
                    auxiliary_prop.remove(0)

                for val in attribute_data['Value']:
                    item = auxiliary_prop.add()
                    item['value'] = val
                    item['aux_type'] = attribute_type

            created_attributes[attribute_type] = material.scs_props[
                "shader_attribute_" + attribute_type]

        elif attribute_type == "substance":

            if not old_value:
                material.scs_props.substance = attribute_data['Value'][0]

    # if shader attribute properties are still unset reset it to default
    if material.scs_props.substance == _MAT_consts.unset_substance and "substance" not in material.scs_props.keys(
    ):
        material.scs_props.substance = "None"

    # collect old uv mappings per tex_coord values and delete them from material (they will be set back later)
    # NOTE: we have to create extra iteration for uv mappings collecting
    # as multiple texture types can use same tex coord and we have to make sure
    # to collect them before we apply any texture data back to material.
    old_texture_mappings = {}
    for tex_type in used_texture_types:

        texture_mappings = getattr(material.scs_props,
                                   "shader_texture_" + tex_type + "_uv")
        if override_back_data:
            while len(texture_mappings) > 0:

                # save only set uv mapping tex_cord:value pairs
                if texture_mappings[0].value != "":
                    old_texture_mappings[texture_mappings[0].
                                         tex_coord] = texture_mappings[0].value

                texture_mappings.remove(0)

    # apply used textures
    created_textures = {}
    created_tex_mappings = []
    for tex_type in used_texture_types:

        # skip unknown texture type
        if tex_type not in material.scs_props.get_texture_types().keys():
            lprint(
                "D Trying to apply unknown texture type to SCS material: %r",
                (tex_type, ))
            continue

        texture_data = used_texture_types[tex_type]

        # always set texture lock attribute
        # important to set it always as some texture might get unlocked in preset and
        # selecting same present again has to unlock that texture
        texture_locked = False
        if "Lock" in texture_data:
            texture_locked = bool(texture_data["Lock"])
        setattr(material.scs_props, "shader_texture_" + tex_type + "_locked",
                texture_locked)

        texture_mappings = getattr(material.scs_props,
                                   "shader_texture_" + tex_type + "_uv")

        # if shader is imported try to create custom tex coord mappings on material
        if material.scs_props.active_shader_preset_name == "<imported>" and "scs_tex_aliases" in material:
            custom_maps = material.scs_props.custom_tex_coord_maps

            for tex_coord_key in sorted(material["scs_tex_aliases"].keys()):

                if _invetory.get_index(custom_maps,
                                       "tex_coord_" + tex_coord_key) == -1:
                    new_map = custom_maps.add()
                    new_map.name = "tex_coord_" + tex_coord_key
                    new_map.value = material["scs_tex_aliases"][tex_coord_key]

            # add one mapping field for using it as a preview uv layer in case of imported shader
            mapping = texture_mappings.add()
            mapping.texture_type = tex_type
            mapping.tex_coord = -1

        # if there is an info about mapping in shader use it (in case of imported material this condition will fall!)
        elif "TexCoord" in texture_data:

            for tex_coord_i, tex_coord in enumerate(texture_data['TexCoord']):
                tex_coord = int(tex_coord)

                if tex_coord != -1:
                    mapping = texture_mappings.add()
                    mapping['texture_type'] = tex_type
                    mapping['tex_coord'] = tex_coord

                    # apply uv mappings either from imported data or from old mappings of previous shader
                    if "scs_tex_aliases" in material:  # scs_tex_aliases are present only on import
                        mapping['value'] = material["scs_tex_aliases"][str(
                            tex_coord)]
                        created_tex_mappings.append(
                            (tex_type, mapping.value, tex_coord))

                    elif tex_coord in old_texture_mappings:

                        mapping['value'] = old_texture_mappings[tex_coord]
                        created_tex_mappings.append(
                            (tex_type, mapping.value, tex_coord))

        # set texture file to current texture
        scs_texture_str = _path.get_scs_texture_str(texture_data['Value'])

        # apply texture path if not empty and not yet set, except if import is going on
        # NOTE: during import bitmap has to be applied even if empty
        # because otherwise texture from previous look might be applied
        if (scs_texture_str != ""
                and getattr(material.scs_props, "shader_texture_" + tex_type,
                            "") == "") or is_import:
            material.scs_props["shader_texture_" + tex_type] = scs_texture_str
            created_textures[tex_type] = get_texture(scs_texture_str, tex_type)

            if is_import:

                # only if shader is imported then make sure that by default imported values will be used
                if material.scs_props.active_shader_preset_name == "<imported>":
                    setattr(material.scs_props,
                            "shader_texture_" + tex_type + "_use_imported",
                            True)
                    setattr(material.scs_props,
                            "shader_texture_" + tex_type + "_imported_tobj",
                            texture_data['Value'])

        # if property is still unset reset it to empty
        if getattr(material.scs_props, "shader_texture_" + tex_type,
                   "") == _MAT_consts.unset_bitmap_filepath:
            material.scs_props["shader_texture_" + tex_type] = ""
        else:

            final_tex_str = getattr(material.scs_props,
                                    "shader_texture_" + tex_type, "")
            created_textures[tex_type] = get_texture(final_tex_str, tex_type)

            if is_import and not override_back_data:

                if created_textures[tex_type] is None:
                    lprint(
                        "E Can't find texture nor TOBJ inside SCS Project Base Path: %r",
                        (final_tex_str, ))

    # override shader data for identifying used attributes and textures in UI
    if override_back_data:

        shader_data = {
            'effect': preset_effect,
            'attributes': attributes,
            'textures': textures
        }
        material["scs_shader_attributes"] = shader_data

    # setup nodes for 3D view visualization
    _shader.setup_nodes(material, preset_effect, created_attributes,
                        created_textures, override_back_data)

    # setup uv mappings to nodes later trough dedicated function, so proper validation is made on tex coord bindings
    for mapping_data in created_tex_mappings:

        # data[0] = texture type;
        # data[1] = uv mapping value;
        # data[2] = tex coord value
        _shader.set_uv(material, mapping_data[0], mapping_data[1],
                       mapping_data[2])
Example #10
0
def set_shader_data_to_material(material, section, preset_effect, is_import=False, override_back_data=True):
    """Used to set up material properties from given shader data even via UI or on import.
    :param material:
    :type material: bpy.types.Material
    :param section:
    :param preset_effect:
    :return:
    """

    attributes = {}
    textures = {}
    attribute_i = 0
    texture_i = 0
    used_attribute_types = {}  # attribute types used by current shader
    used_texture_types = {}  # texture types used by current shader and should be overlooked during clearing of texture slots
    for item in section.sections:

        if item.type == "Attribute":
            attribute_data = {}
            for prop in item.props:
                key, value = prop

                # # GETTING RID OF "[" AND "]" CHARS...
                if type(value) is str:
                    value = value.replace("[", "").replace("]", "")

                attribute_data[key] = value

            attribute_type = attribute_data['Tag']

            attributes[str(attribute_i)] = attribute_data
            attribute_i += 1

            used_attribute_types[attribute_type] = attribute_data

        elif item.type == "Texture":
            texture_data = {}
            for prop in item.props:
                # print('      prop: "%s"' % str(prop))
                texture_data[prop[0]] = prop[1]

            # APPLY SECTION TEXTURE VALUES
            texture_type = texture_data['Tag'].split(':')[1]
            tex_type = texture_type[8:]

            used_texture_types[tex_type] = texture_data

            textures[str(texture_i)] = texture_data
            texture_i += 1

    # clear attribute values for current shader to be stored in blend data block
    # NOTE: looks also takes into account that all the unused properties are omitted from scs_props dict
    scs_props_keys = material.scs_props.keys()
    for key in scs_props_keys:
        is_key_used = False
        if key.startswith("shader_attribute"):
            for used_attribute in used_attribute_types:
                if used_attribute in key[16:]:
                    is_key_used = True

        if key.startswith("shader_texture"):
            for used_tex_type in used_texture_types:
                if used_tex_type in key[14:]:
                    is_key_used = True

        # delete only unused shader keys everything else should stay in the place
        # as those keys might be used in some other way
        if not is_key_used and key.startswith("shader_"):
            lprint("D Unsetting property from material in set_shader_data %s:", (key,))
            material.scs_props.property_unset(key)

    # apply used attributes
    created_attributes = {}
    for attribute_type in used_attribute_types.keys():
        attribute_data = used_attribute_types[attribute_type]
        if attribute_type in ("diffuse", "specular", "env_factor", "fresnel", "tint"):

            material.scs_props["shader_attribute_" + attribute_type] = attribute_data['Value']
            created_attributes[attribute_type] = material.scs_props["shader_attribute_" + attribute_type]

        elif attribute_type in ("shininess", "add_ambient", "reflection", "reflection2", "shadow_bias", "tint_opacity"):

            material.scs_props["shader_attribute_" + attribute_type] = attribute_data['Value'][0]
            created_attributes[attribute_type] = material.scs_props["shader_attribute_" + attribute_type]

        elif attribute_type.startswith("aux") and hasattr(material.scs_props, "shader_attribute_" + attribute_type):

            auxiliary_prop = getattr(material.scs_props, "shader_attribute_" + attribute_type, None)

            # clean old values possible left from previous shader
            while len(auxiliary_prop) > 0:
                auxiliary_prop.remove(0)

            for val in attribute_data['Value']:
                item = auxiliary_prop.add()
                item['value'] = val
                item['aux_type'] = attribute_type

            created_attributes[attribute_type] = material.scs_props["shader_attribute_" + attribute_type]

        elif attribute_type == "substance":

            material.scs_props.substance = attribute_data['Value'][0]

    # if shader attribute properties are still unset reset it to default
    if material.scs_props.substance == _MAT_consts.unset_substance and "substance" not in material.scs_props.keys():
        material.scs_props.substance = "None"

    # apply used textures
    created_textures = {}
    created_tex_uvs = {}
    for tex_type in used_texture_types:
        texture_data = used_texture_types[tex_type]

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

            if "Lock" in texture_data:
                setattr(material.scs_props, "shader_texture_" + tex_type + "_locked", bool(texture_data["Lock"]))

            texture_mappings = getattr(material.scs_props, "shader_texture_" + tex_type + "_uv")
            # clear all texture mapping for current texture from previous shader
            if override_back_data:
                while len(texture_mappings) > 0:
                    texture_mappings.remove(0)

            # if shader is imported try to create custom tex coord mappings on material
            if material.scs_props.active_shader_preset_name == "<imported>" and "scs_tex_aliases" in material:
                custom_maps = material.scs_props.custom_tex_coord_maps

                for tex_coord_key in sorted(material["scs_tex_aliases"].keys()):

                    if _invetory.get_index(custom_maps, "tex_coord_" + tex_coord_key) == -1:
                        new_map = custom_maps.add()
                        new_map.name = "tex_coord_" + tex_coord_key
                        new_map.value = material["scs_tex_aliases"][tex_coord_key]

                # add one mapping field for using it as a preview uv layer in case of imported shader
                mapping = texture_mappings.add()
                mapping.texture_type = tex_type
                mapping.tex_coord = -1

            # if there is an info about mapping in shader use it (in case of imported material this condition will fall!)
            elif "TexCoord" in texture_data:

                for tex_coord in texture_data['TexCoord']:
                    tex_coord = int(tex_coord)

                    if tex_coord != -1:
                        mapping = texture_mappings.add()
                        mapping.texture_type = tex_type
                        mapping.tex_coord = tex_coord

                        if "scs_tex_aliases" in material:
                            mapping.value = material["scs_tex_aliases"][str(tex_coord)]

                            # for now make sure to use only first coord mapping info for shader
                            if len(texture_mappings) == 1:
                                created_tex_uvs[tex_type] = mapping.value

            # set bitmap file to current texture
            bitmap_filepath = _path.get_bitmap_filepath(texture_data['Value'])

            # apply texture path if not empty, except if import is going on
            # NOTE: during import bitmap has to be applied even if empty
            # because otherwise texture from previous look might be applied
            if (bitmap_filepath and bitmap_filepath != "") or is_import:
                material.scs_props["shader_texture_" + tex_type] = bitmap_filepath
                created_textures[tex_type] = get_texture(bitmap_filepath, tex_type)

                if is_import:

                    # only if shader is imported then make sure that by default imported values will be used
                    if material.scs_props.active_shader_preset_name == "<imported>":
                        setattr(material.scs_props, "shader_texture_" + tex_type + "_use_imported", True)
                        setattr(material.scs_props, "shader_texture_" + tex_type + "_imported_tobj", texture_data['Value'])

            # if property is still unset reset it to empty
            if getattr(material.scs_props, "shader_texture_" + tex_type, "") == _MAT_consts.unset_bitmap_filepath:
                material.scs_props["shader_texture_" + tex_type] = ""
            else:
                bitmap_filepath = _path.get_abs_path(getattr(material.scs_props, "shader_texture_" + tex_type, ""))
                created_textures[tex_type] = get_texture(bitmap_filepath, tex_type)

    # override shader data for identifying used attributes and textures in UI
    if override_back_data:

        shader_data = {'effect': preset_effect,
                       'attributes': attributes,
                       'textures': textures}
        material["scs_shader_attributes"] = shader_data

    # setup nodes for 3D view visualization
    _shader.setup_nodes(material, preset_effect, created_attributes, created_textures, created_tex_uvs, override_back_data)
Example #11
0
def set_shader_data_to_material(material, section, preset_effect, is_import=False, override_back_data=True):
    """
    :param material:
    :type material: bpy.types.Material
    :param section:
    :param preset_effect:
    :return:
    """

    defined_tex_types = ("base", "flakenoise", "iamod", "lightmap", "mask", "mult", "oclu", "over", "paintjob", "reflection", "nmap")

    material.use_transparency = preset_effect.endswith(".a")
    _object.set_attr_if_different(material, "transparency_method", "MASK")

    attributes = {}
    textures = {}
    attribute_i = 0
    texture_i = 0
    # dictionary for listing of texture types which are used and should be overlooked during clearing of texture slots
    used_texture_types = {}
    for item in section.sections:

        if item.type == "Attribute":
            attribute_data = {}
            for prop in item.props:
                key, value = prop

                # # GETTING RID OF "[" AND "]" CHARS...
                if type(value) is str:
                    value = value.replace("[", "").replace("]", "")

                attribute_data[key] = value

            attribute_type = attribute_data['Tag']
            # APPLY PRESET ATTRIBUTE VALUES FROM PRESET
            if attribute_type == 'diffuse':
                material.scs_props.shader_attribute_diffuse = attribute_data['Value']
                if is_import:
                    material.scs_props.update_diffuse(material)
            elif attribute_type == 'specular':
                material.scs_props.shader_attribute_specular = attribute_data['Value']
                if is_import:
                    material.scs_props.update_specular(material)
            elif attribute_type == 'shininess':
                material.scs_props.shader_attribute_shininess = attribute_data['Value'][0]
                if is_import:
                    material.scs_props.update_shininess(material)
            elif attribute_type == 'add_ambient':
                material.scs_props.shader_attribute_add_ambient = attribute_data['Value'][0]
                if is_import:
                    material.scs_props.update_add_ambient(material)
            elif attribute_type == 'reflection':
                material.scs_props.shader_attribute_reflection = attribute_data['Value'][0]
                if is_import:
                    material.scs_props.update_reflection(material)
            elif attribute_type == 'reflection2':
                material.scs_props.shader_attribute_reflection2 = attribute_data['Value'][0]
                if is_import:
                    material.scs_props.update_reflection(material)
            elif attribute_type == 'shadow_bias':
                material.scs_props.shader_attribute_shadow_bias = attribute_data['Value'][0]
                if is_import:
                    material.scs_props.update_shadow_bias(material)
            elif attribute_type == 'env_factor':
                material.scs_props.shader_attribute_env_factor = attribute_data['Value']
                if is_import:
                    material.scs_props.update_env_factor(material)
            elif attribute_type == 'fresnel':
                material.scs_props.shader_attribute_fresnel = attribute_data['Value']
            elif attribute_type == 'tint':
                material.scs_props.shader_attribute_tint = attribute_data['Value']
            elif attribute_type == 'tint_opacity':
                material.scs_props.shader_attribute_tint_opacity = attribute_data['Value'][0]
            elif attribute_type in ("aux3", "aux5", "aux6", "aux7", "aux8"):

                auxiliary_prop = getattr(material.scs_props, "shader_attribute_" + attribute_type, None)

                # clean old values possible left from previous shader
                while len(auxiliary_prop) > 0:
                    auxiliary_prop.remove(0)

                for val in attribute_data['Value']:
                    item = auxiliary_prop.add()
                    item.value = val

            attributes[str(attribute_i)] = attribute_data
            attribute_i += 1

        elif item.type == "Texture":
            texture_data = {}
            for prop in item.props:
                # print('      prop: "%s"' % str(prop))
                texture_data[prop[0]] = prop[1]

            # APPLY SECTION TEXTURE VALUES
            texture_type = texture_data['Tag'].split(':')[1]
            slot_id = texture_type[8:]

            # set only defined textures
            if slot_id in defined_tex_types:

                texture_mappings = getattr(material.scs_props, "shader_texture_" + slot_id + "_uv")

                # clear all texture mapping for current texture from previous shader
                if override_back_data:
                    while len(texture_mappings) > 0:
                        texture_mappings.remove(0)

                # if shader is imported try to create custom tex coord mappings on material
                if material.scs_props.active_shader_preset_name == "<imported>" and "scs_tex_aliases" in material:
                    custom_maps = material.scs_props.shader_custom_tex_coord_maps

                    for tex_coord_key in sorted(material["scs_tex_aliases"].keys()):

                        if _invetory.get_index(custom_maps, "tex_coord_" + tex_coord_key) == -1:
                            new_map = custom_maps.add()
                            new_map.name = "tex_coord_" + tex_coord_key
                            new_map.value = material["scs_tex_aliases"][tex_coord_key]

                    # add one mapping field for using it as a preview uv layer in case of imported shader
                    mapping = texture_mappings.add()
                    mapping.texture_type = slot_id
                    mapping.tex_coord = -1

                # if there is an info about mapping in shader use it (in case of imported material this condition will fall!)
                elif "TexCoord" in texture_data:

                    for tex_coord in texture_data['TexCoord']:
                        tex_coord = int(tex_coord)

                        if tex_coord != -1:
                            mapping = texture_mappings.add()
                            mapping.texture_type = slot_id
                            mapping.tex_coord = tex_coord

                            if "scs_tex_aliases" in material:
                                mapping.value = material["scs_tex_aliases"][str(tex_coord)]

                used_texture_types[slot_id] = 1

                bitmap_filepath = _path.get_bitmap_filepath(texture_data['Value'])

                if bitmap_filepath and bitmap_filepath != "":
                    setattr(material.scs_props, "shader_texture_" + slot_id, bitmap_filepath)

                    if is_import:
                        update_texture_slots(material, bitmap_filepath, slot_id)

                        # only if shader is imported then make sure that by default imported values will be used
                        if material.scs_props.active_shader_preset_name == "<imported>":
                            setattr(material.scs_props, "shader_texture_" + slot_id + "_use_imported", True)
                            setattr(material.scs_props, "shader_texture_" + slot_id + "_imported_tobj", texture_data['Value'])

                    texture_slot = get_texture_slot(material, slot_id)
                    if slot_id == 'base' and texture_slot:
                        set_diffuse(texture_slot, material, material.scs_props.shader_attribute_diffuse)
                    elif slot_id == 'reflection' and texture_slot:
                        set_env_factor(texture_slot, material.scs_props.shader_attribute_env_factor)

            textures[str(texture_i)] = texture_data
            texture_i += 1

    if override_back_data:

        # clear texture slots for unused textures from previous preset
        for tex_type in defined_tex_types:
            if tex_type not in used_texture_types:  # delete unused texture slots
                clear_texture_slots(material, tex_type)

        shader_data = {'effect': preset_effect,
                       'attributes': attributes,
                       'textures': textures}
        material["scs_shader_attributes"] = shader_data