Skip to content

Instantly share code, notes, and snippets.

@jrivany jrivany/fix_nif.py
Last active Dec 23, 2019

Embed
What would you like to do?
#!/usr/bin/env python
import argparse, re, os
from pyffi.formats.nif import NifFormat
def process_dir(dir, is_dryrun):
file_changed = False
for stream, data in NifFormat.walkData(args.dir):
try:
# the replace call makes the doctest also pass on windows
os_path = stream.name
split = (os_path.split(os.sep))[-5:]
filename = os.path.join(*split).replace(os.sep, "/")
print("reading %s" % filename)
data.read(stream)
for block in data.blocks:
# Remove NiTexture effect blocks
if isinstance(block, NifFormat.NiTextureEffect):
print('\tremoving NiTextureEffect block')
data.replace_global_node(block, None)
file_changed = True
# Remove NiSourceTextures for bump maps
elif (isinstance(block, NifFormat.NiTexturingProperty)
and block.has_bump_map_texture):
source_block = block.bump_map_texture.source
bump_map_file = str(source_block.file_name)
print('\tremoving NiSourceTexture block with file name %s' % bump_map_file)
data.replace_global_node(source_block, None)
# Remove reference
block.has_bump_map_texture = False
file_changed = True
stream.close()
# Output
if file_changed and not is_dryrun:
print('\twriting to %s' % filename)
output = open(filename, 'wb')
data.write(output)
output.close()
except Exception as e:
print('Error reading file %s' % e)
if __name__ == '__main__':
try:
parser = argparse.ArgumentParser()
parser.add_argument('--dryrun', action='store_true',
help='Print out node deletions and then exit without replacing files')
parser.add_argument('dir', help='The root directory to scan for .nif files.')
args = parser.parse_args()
except Exception:
parser.print_help()
raise SystemExit()
process_dir(args.dir, args.dryrun)
@jrivany

This comment has been minimized.

Copy link
Owner Author

jrivany commented Sep 25, 2017

Example usage inspired by http://openmw.readthedocs.io/en/openmw-0.41.0/openmw-mods/convert_bump_mapped_mods.html#converting-apel-s-various-things-sacks

./fix_nif.py --regex '.*_nm\.dds' PATH_TO_APELS_VAIOUS_THINGS_FOLDER
@jrivany

This comment has been minimized.

Copy link
Owner Author

jrivany commented Jun 7, 2019

Update, regex option is no longer needed, as bump_maps can be found using the block data

@Insidious611

This comment has been minimized.

Copy link

Insidious611 commented Dec 23, 2019

Hi, realize this is just a gist and an old one, but it's giving a screenful of "struct.error: unpack requires a buffer of 2 bytes
Error reading file unpack requires a buffer of 2 bytes" when trying to read the NiTriShapeData struct with pretty much every NIF it encounters.

I'm trying to figure out how to fix it but I've no idea what I'm doing :P

@jrivany

This comment has been minimized.

Copy link
Owner Author

jrivany commented Dec 23, 2019

No worries. Check out this repo https://github.com/treymerkley/openmw-nif-cleaner I've made some fixes and this guy contributed a qt GUI as well.

Anyway since I wrote this, pyffi was updated to break proper support with morrowind nifs (I believe he opened an issue with them about it, perhaps theres a way to make it work with the newer versions)

This will only work with Pyffi 2.2.2, nothing newer, and I'd also recommend checking out the updated processing code in that repo. I can't remember what it fixed, but it works much better

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.