BadDogSkyrim / PyNifly

Export/Import tools between Blender and the Nif format, using Bodyslide/Outfit Studio's Nifly layer. Supports Skyrim LE, Skyrim SE, Fallout 4, Fallout New Vegas, Fallout 76, and Fallout 3.
GNU General Public License v3.0
169 stars 15 forks source link

Textures not loaded if the nif is not in the meshes folder #145

Closed Kalessin42 closed 1 year ago

Kalessin42 commented 1 year ago

This is weird enough that I have to wonder if I'm doing something wrong, but from what I can tell, if a nif is not in the meshes directory when it's imported, then pynifly ignores the textures instead of loading them.

I added Skyrim SE's data directory to the "Asset Libraries" under "File Paths" in blender's preferences so that blender could find the textures. I also converted the textures to png and placed those alongside the dds files so that pynifly had png files to load in place of the dds files. And if a nif is inside the meshes directory inside of Skyrim SE's data directory when I import it, then pynifly loads the textures, and I can see them in blender. However, in all cases that I've tried thus far, if the nif is anywhere else, then the textures do not get loaded.

This is particularly annoying given that nifs used by bodyslide are normally placed in CalienteTools/Bodyslide/ShapeData and nowhere near the meshes directory. It's just the meshes that bodyslide later generates that end up in the meshes directory, and those aren't what you'd normally load into blender. It's the nifs inside of CalienteTools that you'd be importing and working on.

So, maybe I'm doing something wrong, but from what I can tell, pynifly cares about the meshes directory for some reason. The game just loads textures relative to the data directory, and I would expect pynifly to be doing the same, though presumably it has to load relative to the asset libraries or some other path that it's given, since I wouldn't think that it would actually know where the data directory would be otherwise. Either way, pynifly does load the textures correctly if the nif is the meshes directory, so it's clearly finding the data directory and the textures relative to it, but for some reason, it fails to load them if the nif isn't in the meshes directory, and it would be very nice if pynifly would stop treating the meshes directory as something special and loaded the textures for nifs that are elsewhere.

BadDogSkyrim commented 1 year ago

There's code in there that is supposed to look at Blender's file paths if finding it by common root doesn't work. But it's hard to test and I don't use it much so I can't be sure there aren't bugs in there. I'll poke around.

BadDogSkyrim commented 1 year ago

Yeah, so this wasn't working at all. Fixed in next.

Kalessin42 commented 1 year ago

The changes you made definitely improved the situation, because previously, from what I could tell, the textures only got loaded if the nif was in the meshes directory. Now, the textures will load if the nif is directly in the data directory. However, from what I've tested thus far, the textures still don't get loaded if the nif is in a subfolder of the data directory other than meshes, and of course that means that bodyslide nifs don't get their textures loaded, since they're buried in the CalienteTools subdirectory.

So, for instance, if I grab the mod, https://www.nexusmods.com/skyrimspecialedition/mods/92947, use IceStorm's Texture Toolbox to duplicate the texture's as PNGs, and then import CalienteTools\BodySlide\ShapeData\Skintight Dragonwear [3BA]\Skintight Dragonwear [3BA] - Suit.nif from the data directory, I don't get any textures in blender. However, if I copy that nif file into the data directory directly or into somewhere in the meshes directory within the data directory and then import it, then the textures do load in blender.

This is what I have for my blender file path preferences:

blender_file_path_preferences

Is that what I should have to make this work, or do I need to do something else? Or is it that your changes helped but didn't fully fix the problem?

Thanks.

BadDogSkyrim commented 1 year ago

There are two ways to make this work, but either way, you have to honor the texture filepaths in the nif. The only thing you can play with is, since it's a relative filepath, where you start from.

Option 1 is to have all the game files unpacked into a single file tree. So "meshes" and "textures" are both children of a common parent. If you open a nif, the system goes up to that common parent then follows the texture filepath from there. Once it finds the folder holding the texture file, it first looks for a PNG, then for a DDS. So you can translate the DDS files to PNG files in the same folders and you'll get something you can work with in Blender.

Option 2 is to unpack the textures to a folder of your choice and point Blender's "textures" filepath to that folder. It still has to be a full file tree though, because the importer will expect to follow the path from there to the texture file. You can turn all the DDSs into PNGs in this tree (with the texture tools) so you can work with them.

So for a nif in the Bodyslide folders, you have to use the second option. Point Blender's textures folder at the parent of your textures folder (or at the textures folder itself--if one doesn't work try the other). You can use the textures folder in your game directory or unpack to a special folder you make for this purpose.

You seem to be trying to use an asset library, which isn't supported, mostly because I didn't know about them. I'll look and see if that's a location that should be checked also.

Kalessin42 commented 1 year ago

Well, I clearly misunderstood in that I thought that the asset library would be the way to tell blender (and thus the plugin) about the data directory, since from the perspective of the game, the correct way to load the textures is to assume that the path is relative to the data directory. As far as the game is concerned, the location of the nif is irrelevant when loading textures. Programs such as outfit studio and nifskope have settings to tell them where the game's data directory is so that they can find files such as textures, and I wrongly assumed that the blender plugin had to be trying to do the same in some manner.

As a user, ideally, there would be a way to tell the plugin where the data directory is (be it by setting it as an asset library or in some other way) so that the plugin could find the textures without having to put either the nif or the textures anywhere other than where they would normally be in the data directory (or in the data directory as presented to blender via MO2). Barring that though, the plugin documentation should probably be much clearer about how it expects to find the textures. It really doesn't say much on the matter (mostly just mentioning that you need to have the png versions next to the dds versions), and in my case at least, I assumed that it had to be doing something like using the asset libraries to know about the data directory, since the way that the textures for nifs are normally found is by following their paths relative to the data directory. It hadn't occurred to me that anyone would be expecting to have their files be anywhere else or that the plugin would try to find the textures in a completely different manner from the game. I don't know what assumptions other people are making about it though.

So, personally, I'd love it if the plugin could just find the textures via the data directory without my having to put any of the files somewhere special just so that the plugin can find them, but the most important thing here is probably simply that the way that the plugin expects to find the textures is clear. Jumping through extra hoops is annoying, but we do already have to do that by making png files, and at least if the way that the plugin works is clear then it's clear how to take advantage of the feature.

BadDogSkyrim commented 1 year ago

What you're saying you want is pretty much what's implemented now--the difference is that you tell Blender/pynifly where the data directory is through the "textures" filepath, not through an asset library.

I read up on asset libraries and I'm not sure they're intended to do what you want. Looks to me like they're intended to hold Blender elements--data blocks of different types. There's even a note that says image or audio files will be supported in a future version. (Turns out I have one of my game directories set up as an asset library and no files show up.) It might be possible to create an asset library just to use the filepath, but that's janky.

I can improve the documentation.

Kalessin42 commented 1 year ago

Well, from what I'd read (which clearly wasn't enough), I had assumed that the assets libraries would be used as the base directories for the textures path in blender's settings when it was set to // like it defaults to (though doing a bit more reading on it now, it looks like // tells it to load relative to where the blend file is; I don't know what it's supposed to do if you haven't saved anything yet). So, regardless of the plugin's behavior, I had incorrectly understood what blender was doing with the textures path. In any case, if setting that textures path to the data directory works, then I have what I need.

Unfortunately, from what I can tell, setting the textures path to the data directory doesn't work. As before, it succeeds at loading textures when the nif is directly in the data directory or in the meshes directory, but it fails when the nif is in CalienteTools (be it directly in CalienteTools or buried deeper where a bodyslide nif would normally be). It also fails if I create a foobar directory within the data directory and put the nif in there. So, it seems like the meshes directory is being treated special somehow, since the textures do load if the nif is in there. Regardless, setting the textures path to the data directory doesn't seem to do anything for me. And I am using version 9.8.0 of the plugin according to blender, so I don't know if I'm doing something wrong, or if the plugin isn't properly using the textures path or what. There may be another good dose of PEBKAC going on.

BadDogSkyrim commented 1 year ago

The meshes directory is special in that the importer will walk up to that directory, look for a sibling textures directory, and use that as the base for the textures path. Then it's supposed to use blender's textures directory.

But I'm checking it out and having issues. Chasing them now. Once I have a stable system again I'll post a fix.

BadDogSkyrim commented 1 year ago

OK, latest release has my fix for the textures path problem.

Kalessin42 commented 1 year ago

Thanks! It does indeed look like it's working now as long as I have the blender texture path set to the data directory.

And thanks for putting your time into such a useful tool. It really makes modding meshes easier.