Example #1
0
 def export_texture_effect(self, b_texture_node=None):
     """Export a texture effect block from material texture mtex (MTex, not Texture)."""
     texeff = NifFormat.NiTextureEffect()
     texeff.flags = 4
     texeff.rotation.set_identity()
     texeff.scale = 1.0
     texeff.model_projection_matrix.set_identity()
     texeff.texture_filtering = NifFormat.TexFilterMode.FILTER_TRILERP
     texeff.texture_clamping = NifFormat.TexClampMode.WRAP_S_WRAP_T
     texeff.texture_type = NifFormat.EffectType.EFFECT_ENVIRONMENT_MAP
     texeff.coordinate_generation_type = NifFormat.CoordGenType.CG_SPHERE_MAP
     if b_texture_node:
         texeff.source_texture = TextureWriter.export_source_texture(b_texture_node.texture)
         if bpy.context.scene.niftools_scene.game == 'MORROWIND':
             texeff.num_affected_node_list_pointers += 1
             texeff.affected_node_list_pointers.update_size()
     texeff.unknown_vector.x = 1.0
     return block_store.register_block(texeff)
Example #2
0
    def export_source_texture(n_texture=None, filename=None):
        """Export a NiSourceTexture.

        :param n_texture: The n_texture object in blender to be exported.
        :param filename: The full or relative path to the n_texture file
            (this argument is used when exporting NiFlipControllers
            and when exporting default shader slots that have no use in
            being imported into Blender).
        :return: The exported NiSourceTexture block.
        """

        # create NiSourceTexture
        srctex = NifFormat.NiSourceTexture()
        srctex.use_external = True
        if filename is not None:
            # preset filename
            srctex.file_name = filename
        elif n_texture is not None:
            srctex.file_name = TextureWriter.export_texture_filename(n_texture)
        else:
            # this probably should not happen
            NifLog.warn(
                "Exporting source texture without texture or filename (bug?).")

        # fill in default values (TODO: can we use 6 for everything?)
        if bpy.context.scene.niftools_scene.nif_version >= 0x0A000100:
            srctex.pixel_layout = 6
        else:
            srctex.pixel_layout = 5
        srctex.use_mipmaps = 1
        srctex.alpha_format = 3
        srctex.unknown_byte = 1

        # search for duplicate
        for block in block_store.block_to_obj:
            if isinstance(block, NifFormat.NiSourceTexture) and block.get_hash(
            ) == srctex.get_hash():
                return block

        # no identical source texture found, so use and register the new one
        return block_store.register_block(srctex, n_texture)
    def export_properties(self, b_obj, b_mat, n_block):
        """This is the main property processor that attaches
        all suitable properties gauged from b_obj and b_mat to n_block"""

        if b_obj and b_mat:
            # export and add properties to n_block
            for prop in (
                    self.export_alpha_property(b_mat),
                    self.export_wireframe_property(b_obj),
                    self.export_stencil_property(b_mat),
                    self.export_specular_property(b_mat),
                    self.material_property.export_material_property(b_mat)):
                n_block.add_property(prop)

            # todo [property] refactor this
            # add textures
            if bpy.context.scene.niftools_scene.game == 'FALLOUT_3':
                bsshader = self.bss_helper.export_bs_shader_property(b_mat)

                block_store.register_block(bsshader)
                n_block.add_property(bsshader)
            elif bpy.context.scene.niftools_scene.game == 'SKYRIM':
                bsshader = self.bss_helper.export_bs_shader_property(b_mat)

                block_store.register_block(bsshader)
                # TODO [pyffi] Add helper function to allow adding bs_property / general list addition
                n_block.bs_properties[0] = bsshader
                n_block.bs_properties.update_size()

            else:
                if bpy.context.scene.niftools_scene.game in self.texture_helper.USED_EXTRA_SHADER_TEXTURES:
                    # sid meier's railroad and civ4: set shader slots in extra data
                    self.texture_helper.add_shader_integer_extra_datas(n_block)

                n_nitextureprop = self.texture_helper.export_texturing_property(
                    flags=0x0001,  # standard
                    # TODO [object][texture][material] Move out and break dependency
                    applymode=self.texture_helper.
                    get_n_apply_mode_from_b_blend_type('MIX'),
                    b_mat=b_mat)

                block_store.register_block(n_nitextureprop)
                n_block.add_property(n_nitextureprop)
    def export_material_property(self, b_mat, flags=0x0001):
        """Return existing material property with given settings, or create
        a new one if a material property with these settings is not found."""
        # don't export material properties for these games
        if bpy.context.scene.niftools_scene.game in ('SKYRIM', ):
            return
        name = block_store.get_full_name(b_mat)
        # create n_block
        n_mat_prop = NifFormat.NiMaterialProperty()

        # list which determines whether the material name is relevant or not  only for particular names this holds,
        # such as EnvMap2 by default, the material name does not affect rendering
        specialnames = ("EnvMap2", "EnvMap", "skin", "Hair", "dynalpha",
                        "HideSecret", "Lava")

        # hack to preserve EnvMap2, skinm, ... named blocks (even if they got renamed to EnvMap2.xxx or skin.xxx on import)
        if bpy.context.scene.niftools_scene.game in ('OBLIVION', 'FALLOUT_3',
                                                     'SKYRIM'):
            for specialname in specialnames:
                if name.lower() == specialname.lower() or name.lower(
                ).startswith(specialname.lower() + "."):
                    if name != specialname:
                        NifLog.warn(
                            f"Renaming material '{name}' to '{specialname}'")
                    name = specialname

        # clear noname materials
        if name.lower().startswith("noname"):
            NifLog.warn(f"Renaming material '{name}' to ''")
            name = ""

        n_mat_prop.name = name
        # TODO: - standard flag, check? material and texture properties in morrowind style nifs had a flag
        n_mat_prop.flags = flags
        ambient = b_mat.niftools.ambient_color
        n_mat_prop.ambient_color.r = ambient.r
        n_mat_prop.ambient_color.g = ambient.g
        n_mat_prop.ambient_color.b = ambient.b

        # todo [material] some colors in the b2.8 api allow rgb access, others don't - why??
        # diffuse mat
        n_mat_prop.diffuse_color.r, n_mat_prop.diffuse_color.g, n_mat_prop.diffuse_color.b, _ = b_mat.diffuse_color
        n_mat_prop.specular_color.r, n_mat_prop.specular_color.g, n_mat_prop.specular_color.b = b_mat.specular_color

        emissive = b_mat.niftools.emissive_color
        n_mat_prop.emissive_color.r = emissive.r
        n_mat_prop.emissive_color.g = emissive.g
        n_mat_prop.emissive_color.b = emissive.b

        # gloss mat 'Hardness' scrollbar in Blender, takes values between 1 and 511 (MW -> 0.0 - 128.0)
        n_mat_prop.glossiness = b_mat.specular_intensity
        n_mat_prop.alpha = b_mat.niftools.emissive_alpha.v
        # todo [material] this float is used by FO3's material properties
        # n_mat_prop.emit_multi = emitmulti

        # search for duplicate
        # (ignore the name string as sometimes import needs to create different materials even when NiMaterialProperty is the same)
        for n_block in block_store.block_to_obj:
            if not isinstance(n_block, NifFormat.NiMaterialProperty):
                continue

            # when optimization is enabled, ignore material name
            if EXPORT_OPTIMIZE_MATERIALS:
                ignore_strings = not (n_block.name in specialnames)
            else:
                ignore_strings = False

            # check hash
            first_index = 1 if ignore_strings else 0
            if n_block.get_hash()[first_index:] == n_mat_prop.get_hash(
            )[first_index:]:
                NifLog.warn(
                    f"Merging materials '{n_mat_prop.name}' and '{n_block.name}' (they are identical in nif)"
                )
                n_mat_prop = n_block
                break

        block_store.register_block(n_mat_prop)
        # material animation
        self.material_anim.export_material(b_mat, n_mat_prop)
        # no material property with given settings found, so use and register the new one
        return n_mat_prop