basename is now stored in dat_info.json; fixed too many files being added to DatContents, if there were already files in the folder; small UI related things (column fix, files order); fixed WMB import with "only extract" option

This commit is contained in:
ArthurHeitmann
2022-08-23 17:25:22 +02:00
parent 8ed268312b
commit 8850712828
9 changed files with 103 additions and 85 deletions
+3 -14
View File
@@ -234,20 +234,9 @@ def migrateDatDirs():
if dirType["key"] not in bpy.context.scene or len(dirType["newList"]) > 0:
continue
datDir = bpy.context.scene[dirType["key"]]
datInfoJson = ""
fileOrderMetadata = ""
for file in os.listdir(datDir):
if file == "dat_info.json":
datInfoJson = os.path.join(datDir, file)
break
elif file == "file_order.metadata":
fileOrderMetadata = os.path.join(datDir, file)
if datInfoJson:
readJsonDatInfo(datInfoJson, dirType["newList"])
elif fileOrderMetadata:
readFileOrderMetadata(fileOrderMetadata, dirType["newList"])
else:
print("No dat_info.json or file_order.metadata found in " + datDir)
if os.path.isdir(datDir):
if not importContentsFileFromFolder(datDir, dirType["newList"]):
print("No dat_info.json or file_order.metadata found in " + datDir)
## Collision Extras
def setColourByCollisionType(obj):
+1 -1
View File
@@ -17,7 +17,7 @@ class ImportNierCol(bpy.types.Operator, ImportHelper):
def execute(self, context):
from . import col_importer
setExportFieldsFromImportFile(self.filepath)
setExportFieldsFromImportFile(self.filepath, False)
enableCollisionTools()
return col_importer.main(self.filepath)
+11 -21
View File
@@ -8,7 +8,7 @@ from bpy_extras.io_utils import ExportHelper, ImportHelper
from ...consts import DAT_EXTENSIONS
from ...utils.ioUtils import read_uint32
from ...utils.util import readFileOrderMetadata, readJsonDatInfo, saveDatInfo, triangulate_meshes, centre_origins, ShowMessageBox
from ...utils.util import importContentsFileFromFolder, readFileOrderMetadata, readJsonDatInfo, saveDatInfo, triangulate_meshes, centre_origins, ShowMessageBox
class ExportAllSteps(bpy.types.PropertyGroup):
@@ -110,7 +110,8 @@ class DAT_DTT_PT_Export(bpy.types.Panel):
if datType["showVar"]:
box = box.box()
if len(datType["contentsVar"]) > 0:
columns = int(context.region.width / bpy.context.preferences.system.ui_scale // 150)
columns = int(context.region.width / bpy.context.preferences.system.ui_scale // 170)
columns = max(columns, 1)
column = 0
for file in datType["contentsVar"]:
if column % columns == 0:
@@ -259,8 +260,10 @@ class ExportAll(bpy.types.Operator):
elif item.filepath.endswith('.wtp'):
wtpFilePath = item.filepath
datFilePath = os.path.join(datDttExportDir, baseFilename + "." + datExt)
dttFilePath = os.path.join(datDttExportDir, baseFilename + ".dtt")
datFileName = baseFilename + "." + datExt
dttFileName = baseFilename + ".dtt"
datFilePath = os.path.join(datDttExportDir, datFileName)
dttFilePath = os.path.join(datDttExportDir, dttFileName)
from ...wmb.exporter import wmb_exporter
if exportSteps.useWmbStep:
@@ -321,7 +324,7 @@ class ExportAll(bpy.types.Operator):
# save info file
datInfoFilePath = os.path.join(os.path.dirname(file_list[0]), "dat_info.json")
fileNames = [os.path.basename(file_path) for file_path in file_list]
saveDatInfo(datInfoFilePath, fileNames, context.scene.DatExtension)
saveDatInfo(datInfoFilePath, fileNames, datFileName)
# export dtt
export_dat.main(datFilePath, file_list)
exportedFilesCount += 1
@@ -337,7 +340,7 @@ class ExportAll(bpy.types.Operator):
# save info file
datInfoFilePath = os.path.join(os.path.dirname(file_list[0]), "dat_info.json")
fileNames = [os.path.basename(file_path) for file_path in file_list]
saveDatInfo(datInfoFilePath, fileNames, "dtt")
saveDatInfo(datInfoFilePath, fileNames, dttFileName)
# export dtt
export_dat.main(dttFilePath, file_list)
exportedFilesCount += 1
@@ -509,22 +512,9 @@ class ImportDatDttContentsFile(bpy.types.Operator, ImportHelper):
# Parse the appropriate file and add files to contents
root, ext = os.path.splitext(filepath)
if isDir:
# search for metadata or json file
datInfoJson = ""
fileOrderMetadata = ""
for file in os.listdir(filepath):
if file == "dat_info.json":
datInfoJson = os.path.join(filepath, file)
break
elif file == "file_order.metadata":
fileOrderMetadata = os.path.join(filepath, file)
if datInfoJson:
readJsonDatInfo(datInfoJson, contentsList)
elif fileOrderMetadata:
readFileOrderMetadata(fileOrderMetadata, contentsList)
else:
if not importContentsFileFromFolder(filepath, contentsList):
self.report({"ERROR"}, "No 'file_order.metadata' or 'dat_info.json' file found in directory!")
return {"FINISHED"}
return {"CANCELLED"}
elif ext == ".json":
readJsonDatInfo(filepath, contentsList)
elif ext == ".metadata":
+6 -6
View File
@@ -27,16 +27,16 @@ def importDtt(only_extract, filepath):
if not os.path.exists(wmb_filepath):
wmb_filepath = os.path.join(extract_dir, tailless_tail + '.dat', last_filename[:-4] + '.wmb') # if not in dtt, then must be in dat
# WMB
from ...wmb.importer import wmb_importer
wmb_importer.main(only_extract, wmb_filepath)
if only_extract:
return {'FINISHED'}
setExportFieldsFromImportFile(filepath)
setExportFieldsFromImportFile(filepath, True)
enableVisibilitySelector()
# WMB
from ...wmb.importer import wmb_importer
wmb_importer.main(only_extract, wmb_filepath)
# COL
col_filepath = os.path.join(extract_dir, tailless_tail + '.dat', tailless_tail + '.col')
if os.path.isfile(col_filepath):
@@ -108,7 +108,7 @@ class ImportNierDat(bpy.types.Operator, ImportHelper):
if onlyExtract:
return {'FINISHED'}
setExportFieldsFromImportFile(filepath)
setExportFieldsFromImportFile(filepath, True)
# COL
col_filepath = os.path.join(extract_dir, tailless_tail + '.dat', tailless_tail + '.col')
+3 -3
View File
@@ -84,7 +84,7 @@ def extract_file(fp, filename, FileOffset, Size, extract_dir):
def get_all_files(path):
pass
def extract_hashes(fp, extract_dir, FileCount, hashMapOffset, fileNamesOffset, extension):
def extract_hashes(fp, extract_dir, FileCount, hashMapOffset, fileNamesOffset, filename):
create_dir(extract_dir)
# file_order.metadata
@@ -101,7 +101,7 @@ def extract_hashes(fp, extract_dir, FileCount, hashMapOffset, fileNamesOffset, e
saveDatInfo(
extract_dir + '/dat_info.json',
[file.decode('utf-8').rstrip('\x00') for file in fileNames],
extension
filename
)
# hash_data.metadata
@@ -145,7 +145,7 @@ def main(filename, extract_dir, ROOT_DIR):
extract_file(fp, Filename, FileOffset, Size, extract_dir_sub)
extractedFiles += 1
extract_hashes(fp, extract_dir, FileCount, hashMapOffset, NameTableOffset, os.path.splitext(filename)[1][1:])
extract_hashes(fp, extract_dir, FileCount, hashMapOffset, NameTableOffset, os.path.basename(filename))
print(f"[+] {extractedFiles} files extracted from {filename}")
if (FileCount):
return Filename
+1 -1
View File
@@ -16,6 +16,6 @@ class ImportNierLay(bpy.types.Operator, ImportHelper):
def execute(self, context):
from . import lay_importer
setExportFieldsFromImportFile(self.filepath)
setExportFieldsFromImportFile(self.filepath, False)
return lay_importer.main(self.filepath)
+76 -37
View File
@@ -176,39 +176,30 @@ def centre_origins(collection: str):
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
obj.select_set(False)
def setExportFieldsFromImportFile(filepath: str) -> None:
head = os.path.split(filepath)[0]
tail = os.path.split(filepath)[1]
datExt = ".dat" if tail.endswith("dtt") else os.path.splitext(tail)[1]
tailless_tail = tail[:-4]
extract_dir = os.path.join(head, 'nier2blender_extracted')
datDir = os.path.join(extract_dir, tailless_tail + datExt)
if os.path.isdir(datDir) and datExt in DAT_EXTENSIONS:
bpy.context.scene.DatExtension = datExt[1:]
bpy.context.scene.DatContents.clear()
for filename in os.listdir(datDir):
full_path = os.path.join(datDir, filename)
if os.path.isfile(full_path):
name, ext = os.path.splitext(full_path)
if len(ext) > 4:
continue
added_file = bpy.context.scene.DatContents.add()
added_file.filepath = full_path
dttDir = os.path.join(extract_dir, tailless_tail + '.dtt')
if os.path.isdir(dttDir):
bpy.context.scene.DttContents.clear()
for filename in os.listdir(dttDir):
full_path = os.path.join(dttDir, filename)
if os.path.isfile(full_path):
name, ext = os.path.splitext(full_path)
if len(ext) > 4:
continue
added_file = bpy.context.scene.DttContents.add()
added_file.filepath = full_path
bpy.context.scene.ExportFileName = tailless_tail
def setExportFieldsFromImportFile(filepath: str, isDatImport: bool) -> None:
dir = os.path.dirname(filepath)
if isDatImport:
filename = os.path.basename(filepath)
basename, ext = os.path.splitext(filename)
datExt = ext if ext in DAT_EXTENSIONS else ".dat"
datExtractedDir = os.path.join(dir, "nier2blender_extracted", basename + datExt)
dttExtraDir = os.path.join(dir, "nier2blender_extracted", basename + ".dtt")
else:
filename = os.path.basename(dir)
basename, ext = os.path.splitext(filename)
datExt = ext if ext in DAT_EXTENSIONS else ".dat"
parentDir = os.path.dirname(dir)
if ext == ".dtt" or ext in DAT_EXTENSIONS:
datExtractedDir = os.path.join(parentDir, basename + ".dat")
dttExtraDir = os.path.join(parentDir, basename + ".dtt")
else:
print("Unknown DAT folder type")
return
if os.path.exists(datExtractedDir):
importContentsFileFromFolder(datExtractedDir, bpy.context.scene.DatContents)
if os.path.exists(dttExtraDir):
importContentsFileFromFolder(dttExtraDir, bpy.context.scene.DttContents)
def getPreferences():
return bpy.context.preferences.addons[ADDON_NAME].preferences
@@ -271,18 +262,53 @@ def setViewportColorTypeToObject():
space.shading.type = "SOLID"
space.shading.color_type = "OBJECT"
def importContentsFileFromFolder(folderPath: str, contentsList: bpy.types.CollectionProperty) -> bool:
# search for metadata or json file
datInfoJson = ""
fileOrderMetadata = ""
for file in os.listdir(folderPath):
if file == "dat_info.json":
datInfoJson = os.path.join(folderPath, file)
break
elif file == "file_order.metadata":
fileOrderMetadata = os.path.join(folderPath, file)
if datInfoJson:
readJsonDatInfo(datInfoJson, contentsList)
elif fileOrderMetadata:
readFileOrderMetadata(fileOrderMetadata, contentsList)
else:
return False
return True
def getFileSortingKey(file: str):
base, ext = os.path.splitext(file)
return (base.lower(), ext.lower())
def readJsonDatInfo(filepath: str, contentsList: bpy.types.CollectionProperty):
with open(filepath, "r") as f:
filesData = json.load(f)
files = []
dir = os.path.dirname(filepath)
for file in filesData["files"]:
files.append(os.path.join(dir, file))
# remove duplicates and sort
files = list(set(files))
files.sort(key=getFileSortingKey)
for file in files:
added_file = contentsList.add()
added_file.filepath = os.path.join(os.path.dirname(filepath), file)
added_file.filepath = file
# some old dev versions don't have these properties, for backwards compatibility
if "basename" in filesData:
bpy.context.scene.ExportFileName = filesData["basename"]
else:
bpy.context.scene.ExportFileName = os.path.splitext(os.path.basename(dir))[0]
if "ext" in filesData:
if filesData["ext"] != "dtt":
bpy.context.scene.DatExtension = filesData["ext"].lower()
elif not os.path.dirname(filepath).endswith(".dtt"):
bpy.context.scene.DatExtension = "dat"
def readFileOrderMetadata(filepath: str, contentsList: bpy.types.CollectionProperty):
if filepath.endswith("hash_order.metadata"):
@@ -294,15 +320,28 @@ def readFileOrderMetadata(filepath: str, contentsList: bpy.types.CollectionPrope
files = []
for i in range(num_files):
files.append(f.read(name_length).decode("utf-8").strip("\x00"))
# remove duplicates and sort
files = list(set(files))
files.sort(key=getFileSortingKey)
for file in files:
added_file = contentsList.add()
added_file.filepath = os.path.join(os.path.dirname(filepath), file)
ext = os.path.splitext(filepath)[1]
if ext == ".dtt" or ext in DAT_EXTENSIONS:
bpy.context.scene.DatExtension = ext[1:]
bpy.context.scene.ExportFileName = os.path.basename(filepath)[:-4]
def saveDatInfo(filepath: str, files: List[str], ext: str):
def saveDatInfo(filepath: str, files: List[str], filename: str):
files = list(set(files))
files.sort(key=getFileSortingKey)
base, ext = os.path.splitext(filename)
with open(filepath, 'w') as f:
jsonFiles = {
"version": 1,
"files": files,
"ext": ext.lower()
"basename": base,
"ext": ext[1:]
}
json.dump(jsonFiles, f, indent=4)
+1 -1
View File
@@ -21,7 +21,7 @@ class ImportNierWmb(bpy.types.Operator, ImportHelper):
if self.reset_blend:
wmb_importer.reset_blend()
setExportFieldsFromImportFile(self.filepath)
setExportFieldsFromImportFile(self.filepath, False)
enableVisibilitySelector()
return wmb_importer.main(False, self.filepath)
+1 -1
View File
@@ -91,7 +91,7 @@ def importEntities(action: ET.Element, color: List[float], prefix: str) -> None:
for i, entity in enumerate(action.find("layouts").find("normal").find("layouts").findall("value")):
entityId = entity.find("id").text
loc = xmlVecToVec3(entity.find("location").find("position").text)
loc = xmlVecToVec3(entity.find("location").find("position").text) if entity.find("location").find("position") is not None else (0, 0, 0)
rot = xmlVecToVec3(entity.find("location").find("rotation").text) if entity.find("location").find("rotation") is not None else (0, 0, 0)
scale = xmlVecToVec3(entity.find("scale").text) if entity.find("scale") is not None else (1, 1, 1)
entityObjId = entity.find("objId").text if entity.find("objId") is not None else entity.find("objID").text