Пример #1
0
    def run(self):
        """ Randomizes materials for selected objects.
            1. For each object assign a randomly chosen material from the pool.
        """
        self.randomization_level = self.config.get_float(
            "randomization_level", 0.2)
        self._objects_to_manipulate = self.config.get_list(
            'manipulated_objects', get_all_mesh_objects())
        self._materials_to_replace_with = self.config.get_list(
            "materials_to_replace_with", get_all_materials())
        op_mode = self.config.get_string("mode", "once_for_each")

        # if there were no materials selected throw an exception
        if not self._materials_to_replace_with:
            raise Exception("There were no materials selected!")

        if op_mode == "once_for_all":
            random_material = np.random.choice(self._materials_to_replace_with)

        # walk over all objects
        for obj in self._objects_to_manipulate:
            if hasattr(obj, 'material_slots'):
                # walk over all materials
                for material in obj.material_slots:
                    if np.random.uniform(0, 1) <= self.randomization_level:
                        if op_mode == "once_for_each":
                            random_material = np.random.choice(
                                self._materials_to_replace_with)
                        # select a random material to replace the old one with
                        material.material = random_material
Пример #2
0
    def run(self):
        """ Randomizes materials for selected objects.
            1. For each object assign a randomly chosen material from the pool.
        """
        self.randomization_level = self.config.get_float(
            "randomization_level", 0.2)
        self._objects_to_manipulate = self.config.get_list(
            'manipulated_objects', get_all_mesh_objects())
        self._materials_to_replace_with = self.config.get_list(
            "materials_to_replace_with", get_all_materials())
        self._obj_materials_cond_to_be_replaced = self.config.get_raw_dict(
            "obj_materials_cond_to_be_replaced", {})
        op_mode = self.config.get_string("mode", "once_for_each")

        # if there were no materials selected throw an exception
        if not self._materials_to_replace_with:
            print(
                "Warning: No materials selected inside of the MaterialRandomizer!"
            )
            return

        if op_mode == "once_for_all":
            random_material = np.random.choice(self._materials_to_replace_with)

        # walk over all objects
        for obj in self._objects_to_manipulate:
            if hasattr(obj, 'material_slots'):
                # walk over all materials
                for material in obj.material_slots:
                    use_mat = True
                    if self._obj_materials_cond_to_be_replaced:
                        use_mat = len(
                            Material.perform_and_condition_check(
                                self._obj_materials_cond_to_be_replaced, [],
                                [material.material])) == 1
                    if use_mat:
                        if np.random.uniform(0, 1) <= self.randomization_level:
                            if op_mode == "once_for_each":
                                random_material = np.random.choice(
                                    self._materials_to_replace_with)
                            # select a random material to replace the old one with
                            material.material = random_material
Пример #3
0
    def perform_and_condition_check(self, and_condition, materials):
        """ Checks for all materials in the scene if all given conditions are true, collects them in the return list.

        :param and_condition: Given conditions. Type: dict.
        :param objects: Materials, that are already in the return list. Type: list.
        :return: Materials that fulfilled given conditions. Type: list.
        """
        new_materials = []
        # through every material
        for material in get_all_materials():
            if material in new_materials or material in materials:
                continue

            select_material = True
            for key, value in and_condition.items():
                # check if the key is a requested custom property
                requested_custom_property = False
                requested_custom_function = False
                if key.startswith('cp_'):
                    requested_custom_property = True
                    key = key[3:]
                if key.startswith('cf_'):
                    requested_custom_function = True
                    key = key[3:]
                if hasattr(material, key) and not requested_custom_property:
                    # check if the type of the value of attribute matches desired
                    if isinstance(getattr(material, key), type(value)):
                        new_value = value
                    # if not, try to enforce some mathutils-specific type
                    else:
                        if isinstance(getattr(material, key),
                                      mathutils.Vector):
                            new_value = mathutils.Vector(value)
                        elif isinstance(getattr(material, key),
                                        mathutils.Euler):
                            new_value = mathutils.Euler(value)
                        elif isinstance(getattr(material, key),
                                        mathutils.Color):
                            new_value = mathutils.Color(value)
                        # raise an exception if it is none of them
                        else:
                            raise Exception(
                                "Types are not matching: %s and %s !" %
                                (type(getattr(material, key)), type(value)))
                    # or check for equality
                    if not ((isinstance(getattr(material, key), str)
                             and re.fullmatch(value, getattr(material,
                                                             key)) is not None)
                            or getattr(material, key) == new_value):
                        select_material = False
                        break
                # check if a custom property with this name exists
                elif key in material and requested_custom_property:
                    # check if the type of the value of such custom property matches desired
                    if isinstance(material[key], type(value)) or (isinstance(
                            material[key], int) and isinstance(value, bool)):
                        # if it is a string and if the whole string matches the given pattern
                        if not ((isinstance(material[key], str)
                                 and re.fullmatch(value, material[key])
                                 is not None) or material[key] == value):
                            select_material = False
                            break
                    else:
                        # raise an exception if not
                        raise Exception(
                            "Types are not matching: {} and {} !".format(
                                type(material[key]), type(value)))
                elif requested_custom_function:
                    if key.startswith("texture_amount_"):
                        if material.use_nodes:
                            nodes = material.node_tree.nodes
                            texture_nodes = Utility.get_nodes_with_type(
                                nodes, "TexImage")
                            amount_of_texture_nodes = len(
                                texture_nodes
                            ) if texture_nodes is not None else 0
                            if "min" in key:
                                if not (amount_of_texture_nodes >= value):
                                    select_material = False
                                    break
                            elif "max" in key:
                                if not (amount_of_texture_nodes <= value):
                                    select_material = False
                                    break
                            elif "eq" in key:
                                if not (amount_of_texture_nodes == value):
                                    select_material = False
                                    break
                            else:
                                raise Exception(
                                    "This type of key is unknown: {}".format(
                                        key))
                        else:
                            select_material = False
                            break
                    else:
                        select_material = False
                        break
                else:
                    select_material = False
                    break
            if select_material:
                new_materials.append(material)
        return new_materials
Пример #4
0
    def perform_and_condition_check(and_condition,
                                    materials,
                                    used_materials_to_check=None):
        """ Checks for all materials in the scene if all given conditions are true, collects them in the return list.

        :param and_condition: Given conditions. Type: dict.
        :param materials: Materials, that are already in the return list. Type: list.
        :param used_materials_to_check: a list of materials to perform the check on. Type: list. Default: all materials
        :return: Materials that fulfilled given conditions. Type: list.
        """
        new_materials = []
        if used_materials_to_check is None:
            used_materials_to_check = get_all_materials()

        # through every material
        for material in used_materials_to_check:
            if material in new_materials or material in materials or material is None:
                continue

            select_material = True
            for key, value in and_condition.items():
                # check if the key is a requested custom property
                requested_custom_property = False
                requested_custom_function = False
                if key.startswith('cp_'):
                    requested_custom_property = True
                    key = key[3:]
                if key.startswith('cf_'):
                    requested_custom_function = True
                    key = key[3:]
                if hasattr(
                        material, key
                ) and not requested_custom_property and not requested_custom_function:
                    # check if the type of the value of attribute matches desired
                    if isinstance(getattr(material, key), type(value)):
                        new_value = value
                    # if not, try to enforce some mathutils-specific type
                    else:
                        if isinstance(getattr(material, key),
                                      mathutils.Vector):
                            new_value = mathutils.Vector(value)
                        elif isinstance(getattr(material, key),
                                        mathutils.Euler):
                            new_value = mathutils.Euler(value)
                        elif isinstance(getattr(material, key),
                                        mathutils.Color):
                            new_value = mathutils.Color(value)
                        # raise an exception if it is none of them
                        else:
                            raise Exception(
                                "Types are not matching: %s and %s !" %
                                (type(getattr(material, key)), type(value)))
                    # or check for equality
                    if not ((isinstance(getattr(material, key), str)
                             and re.fullmatch(value, getattr(material,
                                                             key)) is not None)
                            or getattr(material, key) == new_value):
                        select_material = False
                        break
                # check if a custom property with this name exists
                elif key in material and requested_custom_property:
                    # check if the type of the value of such custom property matches desired
                    if isinstance(material[key], type(value)) or (isinstance(
                            material[key], int) and isinstance(value, bool)):
                        # if it is a string and if the whole string matches the given pattern
                        if not ((isinstance(material[key], str)
                                 and re.fullmatch(value, material[key])
                                 is not None) or material[key] == value):
                            select_material = False
                            break
                    else:
                        # raise an exception if not
                        raise Exception(
                            "Types are not matching: {} and {} !".format(
                                type(material[key]), type(value)))
                elif requested_custom_function:
                    if key.startswith("texture_amount_"):
                        if material.use_nodes:
                            value = int(value)
                            nodes = material.node_tree.nodes
                            texture_nodes = Utility.get_nodes_with_type(
                                nodes, "TexImage")
                            amount_of_texture_nodes = len(
                                texture_nodes
                            ) if texture_nodes is not None else 0
                            if "min" in key:
                                if not (amount_of_texture_nodes >= value):
                                    select_material = False
                                    break
                            elif "max" in key:
                                if not (amount_of_texture_nodes <= value):
                                    select_material = False
                                    break
                            elif "eq" in key:
                                if not (amount_of_texture_nodes == value):
                                    select_material = False
                                    break
                            else:
                                raise Exception(
                                    "This type of key is unknown: {}".format(
                                        key))
                        else:
                            select_material = False
                            break
                    elif key.startswith("principled_bsdf_amount_"):
                        if material.use_nodes:
                            value = int(value)
                            nodes = material.node_tree.nodes
                            principled = Utility.get_nodes_with_type(
                                nodes, "BsdfPrincipled")
                            amount_of_principled_bsdf_nodes = len(
                                principled) if principled is not None else 0
                            if "min" in key:
                                if not (amount_of_principled_bsdf_nodes >=
                                        value):
                                    select_material = False
                                    break
                            elif "max" in key:
                                if not (amount_of_principled_bsdf_nodes <=
                                        value):
                                    select_material = False
                                    break
                            elif "eq" in key:
                                if not (amount_of_principled_bsdf_nodes
                                        == value):
                                    select_material = False
                                    break
                            else:
                                raise Exception(
                                    "This type of key is unknown: {}".format(
                                        key))
                        else:
                            select_material = False
                            break
                    elif key.startswith("principled_bsdf_"
                                        ):  # must be after the amount check
                        # This custom function can check the value of a certain Principled BSDF shader input.
                        # For example this can be used to avoid using materials, which have an Alpha Texture by
                        # adding they key: `"cf_principled_bsdf_Alpha_eq": 1.0`
                        if material.use_nodes:
                            value = float(value)
                            # first check if there is only one Principled BSDF node in the material
                            nodes = material.node_tree.nodes
                            principled = Utility.get_nodes_with_type(
                                nodes, "BsdfPrincipled")
                            amount_of_principled_bsdf_nodes = len(
                                principled) if principled is not None else 0
                            if amount_of_principled_bsdf_nodes != 1:
                                select_material = False
                                break
                            principled = principled[0]
                            # then extract the input name from the key, for the Alpha example: `Alpha`
                            extracted_input_name = key[len("principled_bsdf_"
                                                           ):key.rfind("_")]
                            # check if this key exists, else throw an error
                            if extracted_input_name not in principled.inputs:
                                raise Exception(
                                    "Only valid inputs of a principled node are allowed: "
                                    "{} in: {}".format(extracted_input_name,
                                                       key))
                            # extract this input value
                            used_value = principled.inputs[
                                extracted_input_name]
                            # if this input value is not a default value it will be connected via the links
                            if len(used_value.links) > 0:
                                select_material = False
                                break
                            # if no link is found check the default value
                            used_value = used_value.default_value
                            # compare the given value to the default value
                            if key.endswith("min"):
                                if not (used_value >= value):
                                    select_material = False
                                    break
                            elif key.endswith("max"):
                                if not (used_value <= value):
                                    select_material = False
                                    break
                            elif key.endswith("eq"):
                                if not (used_value == value):
                                    select_material = False
                                    break
                            else:
                                raise Exception(
                                    "This type of key is unknown: {}".format(
                                        key))
                        else:
                            select_material = False
                            break
                    elif key == "use_materials_of_objects":
                        objects = Utility.build_provider_based_on_config(
                            value).run()
                        found_material = False
                        # iterate over all selected objects
                        for obj in objects:
                            # check if they have materials
                            if hasattr(obj, "material_slots"):
                                for mat_slot in obj.material_slots:
                                    # if the material is the same as the currently checked one
                                    if mat_slot.material == material:
                                        found_material = True
                                        break
                            if found_material:
                                break
                        if not found_material:
                            select_material = False
                            break
                    else:
                        select_material = False
                        break
                else:
                    select_material = False
                    break
            if select_material:
                new_materials.append(material)
        return new_materials