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)
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