diff --git a/CHANGELOG.md b/CHANGELOG.md index ee62d5e..41c7f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,11 @@ * add: kk49: Support for COTW hp_nepal * add: kk49: Support for COTW hp_sh * add: verrasse: Support for COTW the Angler (EGS version) +* add: verrasse: Support for Mad Max (v1.0.3.0 + All DLCs) +* add: verrasse: Support for theHunter Classic (ARC/TAB) +* add: verrasse: Support for theHunter Primal (ARC/TAB) * add: verrasse: Update for latest COTW the Angler (alpheus, belisama, ceto, doris) * add: verrasse / r-one: Added more filenames for COTW the Angler -* add: verrasse: Support for Mad Max (v1.0.3.0 + All DLCs) * add: ash: Added rtpc_v3_flat.ksy * fix: kk49: ADF5 file determination for COTW save files * fix: kk49: hack? empty `gdc/global.gdcc` in COTW now? diff --git a/README.md b/README.md index 96119ab..418cf54 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ Support varies among the games, people are activily using **deca** for GenZero a |---|---| |Avalanche Studios / Systemic Reaction|Generation Zero®| |Avalanche Studios / Expansive Worlds|theHunter™: Call of the Wild| +|Avalanche Studios / Expansive Worlds|theHunter™: Classic| +|Avalanche Studios / Expansive Worlds|theHunter™: Primal| |Avalanche Studios / Expansive Worlds|Call of the Wild: The Angler™| |Avalanche Studios|Just Cause 3| |Avalanche Studios|Just Cause 4| diff --git a/python/deca/deca/db_commands.py b/python/deca/deca/db_commands.py index 2a9111a..fa10b44 100644 --- a/python/deca/deca/db_commands.py +++ b/python/deca/deca/db_commands.py @@ -730,6 +730,9 @@ def process_adf_initial(self, node: VfsNode, db: DbWrap): except EDecaMissingAdfType as ae: self._comm.log('DBCmd: Missing ADF Type {:08x} in {} {} {}'.format( ae.type_id, node.v_hash_to_str(), node.v_path, node.p_path)) + except Exception as e: + self._comm.log('DBCmd: Error parsing ADF [{}] in {} {} {}'.format( + repr(e), node.v_hash_to_str(), node.v_path, node.p_path)) return False def process_rtpc_initial(self, node: VfsNode, db: DbWrap): diff --git a/python/deca/deca/fast_file.py b/python/deca/deca/fast_file.py index 3d4f7db..88983e6 100644 --- a/python/deca/deca/fast_file.py +++ b/python/deca/deca/fast_file.py @@ -83,7 +83,7 @@ def f(buffer, n_buffer, pos, count): ff_read_f64s = make_read_many(np.float64) -@njit(**params) +@njit(**params, boundscheck=True) def ff_read_strz(buffer, n_buffer, pos): pos0 = pos while buffer[pos] != 0 and pos < n_buffer: diff --git a/python/deca/deca/ff_adf.py b/python/deca/deca/ff_adf.py index 7b2f2e1..528cf80 100644 --- a/python/deca/deca/ff_adf.py +++ b/python/deca/deca/ff_adf.py @@ -1088,6 +1088,9 @@ def process_adf_in_exe(self, exepath, node_uid): self.type_missing.add((ae.type_id, node_uid)) self._type_map_updated = True + except Exception as e: + print('Error parsing {:08}.adf in EXE-file at position 0x{}: [{}]'.format(poss, hex(poss), repr(e))) + adf_sub_files.append((poss, adf.total_size)) self.typedefs_add(adf.map_typedef) diff --git a/python/deca/deca/ff_arc_tab.py b/python/deca/deca/ff_arc_tab.py index f4beef7..17a1f04 100644 --- a/python/deca/deca/ff_arc_tab.py +++ b/python/deca/deca/ff_arc_tab.py @@ -12,7 +12,11 @@ def tab_file_load(filename, ver): if magic == b'\x00\x08\x00\x00': - if 2 == ver: + if 10 == ver: + tab_file = TabFileV10() + elif 11 == ver: + tab_file = TabFileV11() + elif 2 == ver: tab_file = TabFileV2() else: unknown_version = True @@ -69,6 +73,48 @@ def serialize(self, f): raise NotImplementedError('Interface Class') +class TabFileV10(TabFileBase): + def __init__(self): + TabFileBase.__init__(self) + + def deserialize(self, f): + self.magic = f.read(4) + + self.file_table = [] + self.file_hash_map = {} + entry = TabEntryFileV10() + while entry.deserialize(f): + self.file_table.append(entry) + self.file_hash_map[entry.hashname] = entry + entry = TabEntryFileV10() + + return True + + def serialize(self, f): + raise NotImplementedError('Interface Class') + + +class TabFileV11(TabFileBase): + def __init__(self): + TabFileBase.__init__(self) + + def deserialize(self, f): + self.magic = f.read(4) + + self.file_table = [] + self.file_hash_map = {} + entry = TabEntryFileV11() + while entry.deserialize(f): + self.file_table.append(entry) + self.file_hash_map[entry.hashname] = entry + entry = TabEntryFileV11() + + return True + + def serialize(self, f): + raise NotImplementedError('Interface Class') + + class TabFileV2(TabFileBase): def __init__(self): TabFileBase.__init__(self) @@ -262,6 +308,53 @@ def debug(self): ] +class TabEntryFileV10(TabEntryFileBase): + def __init__(self): + TabEntryFileBase.__init__(self) + + def deserialize(self, f): + try: + self.hashname = f.read_u32(raise_on_no_data=True) + self.offset = f.read_u32(raise_on_no_data=True) + self.size_c = f.read_u32(raise_on_no_data=True) + self.size_u = self.size_c + self.compression_type = compression_00_none + self.compression_flags = f.read_u32(raise_on_no_data=True) + + if f.debug: + self.debug() + except EDecaOutOfData: + return False + + return True + + def serialize(self, f): + raise NotImplementedError('TODO') + + +class TabEntryFileV11(TabEntryFileBase): + def __init__(self): + TabEntryFileBase.__init__(self) + + def deserialize(self, f): + try: + self.hashname = f.read_u32(raise_on_no_data=True) + self.offset = f.read_u32(raise_on_no_data=True) + self.size_c = f.read_u32(raise_on_no_data=True) + self.size_u = self.size_c + self.compression_type = compression_00_none + + if f.debug: + self.debug() + except EDecaOutOfData: + return False + + return True + + def serialize(self, f): + raise NotImplementedError('TODO') + + class TabEntryFileV2(TabEntryFileBase): def __init__(self): TabEntryFileBase.__init__(self) diff --git a/python/deca_gui/deca_gui/main.py b/python/deca_gui/deca_gui/main.py index 4832b04..fd44281 100644 --- a/python/deca_gui/deca_gui/main.py +++ b/python/deca_gui/deca_gui/main.py @@ -239,11 +239,19 @@ def update_ui_state(self): self.ui.bt_mod_build.setEnabled(False) self.ui.action_external_add.setEnabled(False) self.ui.action_make_web_map.setEnabled(False) + self.ui.tab_extract.setEnabled(False) + self.ui.tab_modding.setEnabled(False) + self.ui.tab_3d_gltf2.setEnabled(False) + self.ui.tab_utils.setEnabled(False) else: self.ui.bt_mod_build_folder_show.setEnabled(True) self.ui.bt_mod_build.setEnabled(True) self.ui.action_external_add.setEnabled(True) self.ui.action_make_web_map.setEnabled(True) + self.ui.tab_extract.setEnabled(True) + self.ui.tab_modding.setEnabled(True) + self.ui.tab_3d_gltf2.setEnabled(True) + self.ui.tab_utils.setEnabled(True) self.filter_text_changed() def update_select_state(self, vfs_view): @@ -266,10 +274,10 @@ def update_select_state(self, vfs_view): self.ui.bt_mod_prep.setText('PREP MOD: {}'.format(str_vpaths)) if self.ui.chkbx_mod_build_subset.isChecked(): - self.ui.bt_mod_build.setText('Build Mod Subset: {}'.format(str_vpaths)) + self.ui.bt_mod_build.setText('BUILD MOD SUBSET: {}'.format(str_vpaths)) self.ui.bt_mod_build.setEnabled(any_selected) else: - self.ui.bt_mod_build.setText('Build Mod All') + self.ui.bt_mod_build.setText('BUILD MOD ALL') def vnode_2click_selected(self, uids: List[int]): self.current_uids = uids @@ -371,7 +379,8 @@ def slot_extract_gltf_clicked(self, checked): texture_format=self.ui.cmbbx_texture_format.currentText()) def slot_mod_build_subset_clicked(self, checked): - self.update_select_state(self.vfs_view_current()) + if self.vfs_view_current(): + self.update_select_state(self.vfs_view_current()) def slot_mod_prep_clicked(self, checked): if self.vfs_view_current(): diff --git a/python/deca_gui/deca_gui/main_window.py b/python/deca_gui/deca_gui/main_window.py index ec27742..cbde22f 100644 --- a/python/deca_gui/deca_gui/main_window.py +++ b/python/deca_gui/deca_gui/main_window.py @@ -3,23 +3,32 @@ ################################################################################ ## Form generated from reading UI file 'main_window.ui' ## -## Created by: Qt User Interface Compiler version 5.15.2 +## Created by: Qt User Interface Compiler version 6.8.1 ## ## WARNING! All changes made in this file will be lost when recompiling UI file! ################################################################################ -from PySide6.QtCore import * -from PySide6.QtGui import * -from PySide6.QtWidgets import * +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient, + QCursor, QFont, QFontDatabase, QGradient, + QIcon, QImage, QKeySequence, QLinearGradient, + QPainter, QPalette, QPixmap, QRadialGradient, + QTransform) +from PySide6.QtWidgets import (QApplication, QCheckBox, QComboBox, QGridLayout, + QHBoxLayout, QLabel, QLineEdit, QMainWindow, + QMenu, QMenuBar, QPushButton, QSizePolicy, + QSpacerItem, QSplitter, QStatusBar, QTabWidget, + QVBoxLayout, QWidget) from .dataviewwidget import DataViewWidget - class Ui_MainWindow(object): def setupUi(self, MainWindow): if not MainWindow.objectName(): MainWindow.setObjectName(u"MainWindow") - MainWindow.resize(960, 603) + MainWindow.resize(960, 600) self.action_project_new = QAction(MainWindow) self.action_project_new.setObjectName(u"action_project_new") self.action_project_open = QAction(MainWindow) @@ -34,286 +43,299 @@ def setupUi(self, MainWindow): self.action_file_gz_open.setObjectName(u"action_file_gz_open") self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") - self.verticalLayout_2 = QVBoxLayout(self.centralwidget) - self.verticalLayout_2.setSpacing(7) - self.verticalLayout_2.setObjectName(u"verticalLayout_2") - self.verticalLayout_2.setContentsMargins(-1, 11, 11, 0) + self.centralwidget_layout = QVBoxLayout(self.centralwidget) + self.centralwidget_layout.setObjectName(u"centralwidget_layout") self.splitter = QSplitter(self.centralwidget) self.splitter.setObjectName(u"splitter") - self.splitter.setOrientation(Qt.Horizontal) + self.splitter.setOrientation(Qt.Orientation.Horizontal) self.splitter.setHandleWidth(7) self.splitter.setChildrenCollapsible(False) self.layoutWidget = QWidget(self.splitter) self.layoutWidget.setObjectName(u"layoutWidget") - self.verticalLayout = QVBoxLayout(self.layoutWidget) - self.verticalLayout.setObjectName(u"verticalLayout") - self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.vertical_layout = QVBoxLayout(self.layoutWidget) + self.vertical_layout.setObjectName(u"vertical_layout") + self.vertical_layout.setContentsMargins(0, 0, 0, 0) self.tabs_nodes = QTabWidget(self.layoutWidget) self.tabs_nodes.setObjectName(u"tabs_nodes") self.tabs_nodes.setTabsClosable(True) - self.verticalLayout.addWidget(self.tabs_nodes) + self.vertical_layout.addWidget(self.tabs_nodes) - self.horizontalLayout = QHBoxLayout() - self.horizontalLayout.setObjectName(u"horizontalLayout") - self.horizontalLayout.setContentsMargins(1, 1, 1, 1) + self.horizontal_layout = QHBoxLayout() + self.horizontal_layout.setObjectName(u"horizontal_layout") + self.horizontal_layout.setContentsMargins(1, 1, 1, 1) self.filter_label = QLabel(self.layoutWidget) self.filter_label.setObjectName(u"filter_label") - self.horizontalLayout.addWidget(self.filter_label) + self.horizontal_layout.addWidget(self.filter_label) self.filter_edit = QLineEdit(self.layoutWidget) self.filter_edit.setObjectName(u"filter_edit") + sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Ignored) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.filter_edit.sizePolicy().hasHeightForWidth()) + self.filter_edit.setSizePolicy(sizePolicy) - self.horizontalLayout.addWidget(self.filter_edit) + self.horizontal_layout.addWidget(self.filter_edit) self.filter_set_bt = QPushButton(self.layoutWidget) self.filter_set_bt.setObjectName(u"filter_set_bt") - self.horizontalLayout.addWidget(self.filter_set_bt) + self.horizontal_layout.addWidget(self.filter_set_bt) self.filter_clear_bt = QPushButton(self.layoutWidget) self.filter_clear_bt.setObjectName(u"filter_clear_bt") - self.horizontalLayout.addWidget(self.filter_clear_bt) + self.horizontal_layout.addWidget(self.filter_clear_bt) + self.horizontal_layout.setStretch(1, 1) - self.verticalLayout.addLayout(self.horizontalLayout) + self.vertical_layout.addLayout(self.horizontal_layout) self.tabs_control = QTabWidget(self.layoutWidget) self.tabs_control.setObjectName(u"tabs_control") self.tab_extract = QWidget() self.tab_extract.setObjectName(u"tab_extract") - self.gridLayout = QGridLayout(self.tab_extract) - self.gridLayout.setObjectName(u"gridLayout") + self.grid_layout_1 = QGridLayout(self.tab_extract) + self.grid_layout_1.setObjectName(u"grid_layout_1") self.cmbbx_map_format = QComboBox(self.tab_extract) self.cmbbx_map_format.addItem("") self.cmbbx_map_format.addItem("") self.cmbbx_map_format.addItem("") self.cmbbx_map_format.setObjectName(u"cmbbx_map_format") - sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.cmbbx_map_format.sizePolicy().hasHeightForWidth()) - self.cmbbx_map_format.setSizePolicy(sizePolicy) + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.cmbbx_map_format.sizePolicy().hasHeightForWidth()) + self.cmbbx_map_format.setSizePolicy(sizePolicy1) + self.cmbbx_map_format.setMinimumSize(QSize(96, 0)) - self.gridLayout.addWidget(self.cmbbx_map_format, 4, 1, 1, 2) + self.grid_layout_1.addWidget(self.cmbbx_map_format, 4, 1, 1, 2) self.chkbx_export_contents_extract = QCheckBox(self.tab_extract) self.chkbx_export_contents_extract.setObjectName(u"chkbx_export_contents_extract") - self.gridLayout.addWidget(self.chkbx_export_contents_extract, 2, 0, 1, 1) + self.grid_layout_1.addWidget(self.chkbx_export_contents_extract, 2, 0, 1, 1) self.chkbx_export_text_extract = QCheckBox(self.tab_extract) self.chkbx_export_text_extract.setObjectName(u"chkbx_export_text_extract") - self.gridLayout.addWidget(self.chkbx_export_text_extract, 3, 0, 1, 1) + self.grid_layout_1.addWidget(self.chkbx_export_text_extract, 3, 0, 1, 1) self.chkbx_export_map = QCheckBox(self.tab_extract) self.chkbx_export_map.setObjectName(u"chkbx_export_map") - self.gridLayout.addWidget(self.chkbx_export_map, 4, 0, 1, 1) + self.grid_layout_1.addWidget(self.chkbx_export_map, 4, 0, 1, 1) self.chkbx_export_raw_extract = QCheckBox(self.tab_extract) self.chkbx_export_raw_extract.setObjectName(u"chkbx_export_raw_extract") - self.gridLayout.addWidget(self.chkbx_export_raw_extract, 0, 0, 1, 1) + self.grid_layout_1.addWidget(self.chkbx_export_raw_extract, 0, 0, 1, 1) self.chkbx_export_processed_extract = QCheckBox(self.tab_extract) self.chkbx_export_processed_extract.setObjectName(u"chkbx_export_processed_extract") - self.gridLayout.addWidget(self.chkbx_export_processed_extract, 1, 0, 1, 1) + self.grid_layout_1.addWidget(self.chkbx_export_processed_extract, 1, 0, 1, 1) self.bt_extract = QPushButton(self.tab_extract) self.bt_extract.setObjectName(u"bt_extract") - self.bt_extract.setIconSize(QSize(18, 18)) - self.gridLayout.addWidget(self.bt_extract, 0, 2, 1, 2) + self.grid_layout_1.addWidget(self.bt_extract, 0, 2, 1, 2) self.bt_extract_folder_show = QPushButton(self.tab_extract) self.bt_extract_folder_show.setObjectName(u"bt_extract_folder_show") - sizePolicy.setHeightForWidth(self.bt_extract_folder_show.sizePolicy().hasHeightForWidth()) - self.bt_extract_folder_show.setSizePolicy(sizePolicy) - self.bt_extract_folder_show.setIconSize(QSize(18, 18)) + sizePolicy1.setHeightForWidth(self.bt_extract_folder_show.sizePolicy().hasHeightForWidth()) + self.bt_extract_folder_show.setSizePolicy(sizePolicy1) - self.gridLayout.addWidget(self.bt_extract_folder_show, 0, 1, 1, 1) + self.grid_layout_1.addWidget(self.bt_extract_folder_show, 0, 1, 1, 1) - self.tab_extract_hspacer = QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.tab_extract_hspacer = QSpacerItem(0, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) - self.gridLayout.addItem(self.tab_extract_hspacer, 0, 4, 1, 1) + self.grid_layout_1.addItem(self.tab_extract_hspacer, 0, 4, 1, 1) - self.gridLayout.setRowMinimumHeight(0, 28) - self.gridLayout.setRowMinimumHeight(1, 28) - self.gridLayout.setRowMinimumHeight(2, 28) - self.gridLayout.setRowMinimumHeight(3, 28) - self.gridLayout.setRowMinimumHeight(4, 28) + self.grid_layout_1.setRowMinimumHeight(0, 24) + self.grid_layout_1.setRowMinimumHeight(1, 24) + self.grid_layout_1.setRowMinimumHeight(2, 24) + self.grid_layout_1.setRowMinimumHeight(3, 24) + self.grid_layout_1.setRowMinimumHeight(4, 24) self.tabs_control.addTab(self.tab_extract, "") self.tab_modding = QWidget() self.tab_modding.setObjectName(u"tab_modding") - self.gridLayout_3 = QGridLayout(self.tab_modding) - self.gridLayout_3.setObjectName(u"gridLayout_3") + self.grid_layout_2 = QGridLayout(self.tab_modding) + self.grid_layout_2.setObjectName(u"grid_layout_2") self.chkbx_export_processed_mods = QCheckBox(self.tab_modding) self.chkbx_export_processed_mods.setObjectName(u"chkbx_export_processed_mods") - self.gridLayout_3.addWidget(self.chkbx_export_processed_mods, 1, 0, 1, 1) + self.grid_layout_2.addWidget(self.chkbx_export_processed_mods, 1, 0, 1, 1) self.chkbx_mod_build_subset = QCheckBox(self.tab_modding) self.chkbx_mod_build_subset.setObjectName(u"chkbx_mod_build_subset") - self.gridLayout_3.addWidget(self.chkbx_mod_build_subset, 3, 0, 1, 1) + self.grid_layout_2.addWidget(self.chkbx_mod_build_subset, 3, 0, 1, 1) self.bt_mod_folder_show = QPushButton(self.tab_modding) self.bt_mod_folder_show.setObjectName(u"bt_mod_folder_show") - sizePolicy.setHeightForWidth(self.bt_mod_folder_show.sizePolicy().hasHeightForWidth()) - self.bt_mod_folder_show.setSizePolicy(sizePolicy) - self.bt_mod_folder_show.setIconSize(QSize(18, 18)) + sizePolicy1.setHeightForWidth(self.bt_mod_folder_show.sizePolicy().hasHeightForWidth()) + self.bt_mod_folder_show.setSizePolicy(sizePolicy1) - self.gridLayout_3.addWidget(self.bt_mod_folder_show, 0, 1, 1, 1) + self.grid_layout_2.addWidget(self.bt_mod_folder_show, 0, 1, 1, 1) self.chkbx_export_raw_mods = QCheckBox(self.tab_modding) self.chkbx_export_raw_mods.setObjectName(u"chkbx_export_raw_mods") - self.gridLayout_3.addWidget(self.chkbx_export_raw_mods, 0, 0, 1, 1) + self.grid_layout_2.addWidget(self.chkbx_export_raw_mods, 0, 0, 1, 1) self.bt_mod_prep = QPushButton(self.tab_modding) self.bt_mod_prep.setObjectName(u"bt_mod_prep") - self.bt_mod_prep.setIconSize(QSize(18, 18)) - self.gridLayout_3.addWidget(self.bt_mod_prep, 0, 2, 1, 1) + self.grid_layout_2.addWidget(self.bt_mod_prep, 0, 2, 1, 1) self.bt_mod_build = QPushButton(self.tab_modding) self.bt_mod_build.setObjectName(u"bt_mod_build") - self.bt_mod_build.setIconSize(QSize(18, 18)) - self.gridLayout_3.addWidget(self.bt_mod_build, 1, 2, 1, 1) + self.grid_layout_2.addWidget(self.bt_mod_build, 1, 2, 1, 1) self.chkbx_export_contents_mods = QCheckBox(self.tab_modding) self.chkbx_export_contents_mods.setObjectName(u"chkbx_export_contents_mods") - self.gridLayout_3.addWidget(self.chkbx_export_contents_mods, 2, 0, 1, 1) + self.grid_layout_2.addWidget(self.chkbx_export_contents_mods, 2, 0, 1, 1) self.bt_mod_build_folder_show = QPushButton(self.tab_modding) self.bt_mod_build_folder_show.setObjectName(u"bt_mod_build_folder_show") - sizePolicy.setHeightForWidth(self.bt_mod_build_folder_show.sizePolicy().hasHeightForWidth()) - self.bt_mod_build_folder_show.setSizePolicy(sizePolicy) - self.bt_mod_build_folder_show.setIconSize(QSize(18, 18)) + sizePolicy1.setHeightForWidth(self.bt_mod_build_folder_show.sizePolicy().hasHeightForWidth()) + self.bt_mod_build_folder_show.setSizePolicy(sizePolicy1) - self.gridLayout_3.addWidget(self.bt_mod_build_folder_show, 1, 1, 1, 1) + self.grid_layout_2.addWidget(self.bt_mod_build_folder_show, 1, 1, 1, 1) self.chkbx_mod_do_not_build_archives = QCheckBox(self.tab_modding) self.chkbx_mod_do_not_build_archives.setObjectName(u"chkbx_mod_do_not_build_archives") - self.gridLayout_3.addWidget(self.chkbx_mod_do_not_build_archives, 4, 0, 1, 3) + self.grid_layout_2.addWidget(self.chkbx_mod_do_not_build_archives, 4, 0, 1, 3) - self.tab_modding_hspacer = QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.tab_modding_hspacer = QSpacerItem(0, 0, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) - self.gridLayout_3.addItem(self.tab_modding_hspacer, 0, 3, 1, 1) + self.grid_layout_2.addItem(self.tab_modding_hspacer, 0, 3, 1, 1) - self.gridLayout_3.setRowMinimumHeight(0, 28) - self.gridLayout_3.setRowMinimumHeight(1, 28) - self.gridLayout_3.setRowMinimumHeight(2, 28) - self.gridLayout_3.setRowMinimumHeight(3, 28) - self.gridLayout_3.setRowMinimumHeight(4, 28) + self.grid_layout_2.setRowMinimumHeight(0, 24) + self.grid_layout_2.setRowMinimumHeight(1, 24) + self.grid_layout_2.setRowMinimumHeight(2, 24) + self.grid_layout_2.setRowMinimumHeight(3, 24) + self.grid_layout_2.setRowMinimumHeight(4, 24) self.tabs_control.addTab(self.tab_modding, "") self.tab_3d_gltf2 = QWidget() self.tab_3d_gltf2.setObjectName(u"tab_3d_gltf2") - self.gridLayout_2 = QGridLayout(self.tab_3d_gltf2) - self.gridLayout_2.setObjectName(u"gridLayout_2") - self.bt_extract_gltf_3d_folder_show = QPushButton(self.tab_3d_gltf2) - self.bt_extract_gltf_3d_folder_show.setObjectName(u"bt_extract_gltf_3d_folder_show") - sizePolicy.setHeightForWidth(self.bt_extract_gltf_3d_folder_show.sizePolicy().hasHeightForWidth()) - self.bt_extract_gltf_3d_folder_show.setSizePolicy(sizePolicy) - self.bt_extract_gltf_3d_folder_show.setIconSize(QSize(18, 18)) - - self.gridLayout_2.addWidget(self.bt_extract_gltf_3d_folder_show, 0, 1, 1, 1) - + self.grid_layout_3 = QGridLayout(self.tab_3d_gltf2) + self.grid_layout_3.setObjectName(u"grid_layout_3") self.chkbx_export_save_to_one_dir = QCheckBox(self.tab_3d_gltf2) self.chkbx_export_save_to_one_dir.setObjectName(u"chkbx_export_save_to_one_dir") - self.gridLayout_2.addWidget(self.chkbx_export_save_to_one_dir, 0, 0, 1, 1) + self.grid_layout_3.addWidget(self.chkbx_export_save_to_one_dir, 0, 0, 1, 1) - self.chkbx_export_3d_include_skeleton = QCheckBox(self.tab_3d_gltf2) - self.chkbx_export_3d_include_skeleton.setObjectName(u"chkbx_export_3d_include_skeleton") + self.cmbbx_texture_format = QComboBox(self.tab_3d_gltf2) + self.cmbbx_texture_format.addItem("") + self.cmbbx_texture_format.addItem("") + self.cmbbx_texture_format.addItem("") + self.cmbbx_texture_format.setObjectName(u"cmbbx_texture_format") + sizePolicy1.setHeightForWidth(self.cmbbx_texture_format.sizePolicy().hasHeightForWidth()) + self.cmbbx_texture_format.setSizePolicy(sizePolicy1) + self.cmbbx_texture_format.setMinimumSize(QSize(64, 0)) + + self.grid_layout_3.addWidget(self.cmbbx_texture_format, 4, 1, 1, 2) + + self.bt_extract_gltf_3d_folder_show = QPushButton(self.tab_3d_gltf2) + self.bt_extract_gltf_3d_folder_show.setObjectName(u"bt_extract_gltf_3d_folder_show") + sizePolicy1.setHeightForWidth(self.bt_extract_gltf_3d_folder_show.sizePolicy().hasHeightForWidth()) + self.bt_extract_gltf_3d_folder_show.setSizePolicy(sizePolicy1) + + self.grid_layout_3.addWidget(self.bt_extract_gltf_3d_folder_show, 0, 1, 1, 1) - self.gridLayout_2.addWidget(self.chkbx_export_3d_include_skeleton, 1, 0, 1, 1) + self.tab_3d_hspacer = QSpacerItem(40, 20, QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Minimum) + + self.grid_layout_3.addItem(self.tab_3d_hspacer, 0, 3, 1, 1) self.lbl_texture_format = QLabel(self.tab_3d_gltf2) self.lbl_texture_format.setObjectName(u"lbl_texture_format") + sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Fixed) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth(self.lbl_texture_format.sizePolicy().hasHeightForWidth()) + self.lbl_texture_format.setSizePolicy(sizePolicy2) - self.gridLayout_2.addWidget(self.lbl_texture_format, 3, 0, 1, 1) + self.grid_layout_3.addWidget(self.lbl_texture_format, 4, 0, 1, 1) - self.bt_extract_gltf_3d = QPushButton(self.tab_3d_gltf2) - self.bt_extract_gltf_3d.setObjectName(u"bt_extract_gltf_3d") - self.bt_extract_gltf_3d.setIconSize(QSize(18, 18)) + self.chkbx_export_3d_include_skeleton = QCheckBox(self.tab_3d_gltf2) + self.chkbx_export_3d_include_skeleton.setObjectName(u"chkbx_export_3d_include_skeleton") - self.gridLayout_2.addWidget(self.bt_extract_gltf_3d, 0, 2, 1, 2) + self.grid_layout_3.addWidget(self.chkbx_export_3d_include_skeleton, 1, 0, 1, 1) - self.cmbbx_texture_format = QComboBox(self.tab_3d_gltf2) - self.cmbbx_texture_format.addItem("") - self.cmbbx_texture_format.addItem("") - self.cmbbx_texture_format.addItem("") - self.cmbbx_texture_format.setObjectName(u"cmbbx_texture_format") - sizePolicy.setHeightForWidth(self.cmbbx_texture_format.sizePolicy().hasHeightForWidth()) - self.cmbbx_texture_format.setSizePolicy(sizePolicy) + self.bt_extract_gltf_3d = QPushButton(self.tab_3d_gltf2) + self.bt_extract_gltf_3d.setObjectName(u"bt_extract_gltf_3d") - self.gridLayout_2.addWidget(self.cmbbx_texture_format, 3, 1, 1, 2) + self.grid_layout_3.addWidget(self.bt_extract_gltf_3d, 0, 2, 1, 1) - self.tab_3d_hspacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.tab_32_label_1 = QLabel(self.tab_3d_gltf2) + self.tab_32_label_1.setObjectName(u"tab_32_label_1") + sizePolicy2.setHeightForWidth(self.tab_32_label_1.sizePolicy().hasHeightForWidth()) + self.tab_32_label_1.setSizePolicy(sizePolicy2) - self.gridLayout_2.addItem(self.tab_3d_hspacer, 0, 4, 1, 1) + self.grid_layout_3.addWidget(self.tab_32_label_1, 2, 0, 1, 1) - self.tab_3d_vspacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.tab_32_label_2 = QLabel(self.tab_3d_gltf2) + self.tab_32_label_2.setObjectName(u"tab_32_label_2") + sizePolicy2.setHeightForWidth(self.tab_32_label_2.sizePolicy().hasHeightForWidth()) + self.tab_32_label_2.setSizePolicy(sizePolicy2) - self.gridLayout_2.addItem(self.tab_3d_vspacer, 2, 4, 1, 1) + self.grid_layout_3.addWidget(self.tab_32_label_2, 3, 0, 1, 1) - self.gridLayout_2.setRowMinimumHeight(0, 28) - self.gridLayout_2.setRowMinimumHeight(1, 28) - self.gridLayout_2.setRowMinimumHeight(2, 28) - self.gridLayout_2.setRowMinimumHeight(3, 28) + self.grid_layout_3.setRowMinimumHeight(0, 24) + self.grid_layout_3.setRowMinimumHeight(1, 24) + self.grid_layout_3.setRowMinimumHeight(2, 24) + self.grid_layout_3.setRowMinimumHeight(3, 24) + self.grid_layout_3.setRowMinimumHeight(4, 24) self.tabs_control.addTab(self.tab_3d_gltf2, "") self.tab_utils = QWidget() self.tab_utils.setObjectName(u"tab_utils") - self.gridLayout_4 = QGridLayout(self.tab_utils) - self.gridLayout_4.setObjectName(u"gridLayout_4") + self.grid_layout_4 = QGridLayout(self.tab_utils) + self.grid_layout_4.setObjectName(u"grid_layout_4") + self.vhash_to_vpath_out_edit = QLineEdit(self.tab_utils) + self.vhash_to_vpath_out_edit.setObjectName(u"vhash_to_vpath_out_edit") + self.vhash_to_vpath_out_edit.setReadOnly(True) + + self.grid_layout_4.addWidget(self.vhash_to_vpath_out_edit, 0, 2, 1, 1) + self.vhash_to_vpath_label = QLabel(self.tab_utils) self.vhash_to_vpath_label.setObjectName(u"vhash_to_vpath_label") - self.gridLayout_4.addWidget(self.vhash_to_vpath_label, 0, 0, 1, 1) + self.grid_layout_4.addWidget(self.vhash_to_vpath_label, 0, 0, 1, 1) self.vhash_to_vpath_in_edit = QLineEdit(self.tab_utils) self.vhash_to_vpath_in_edit.setObjectName(u"vhash_to_vpath_in_edit") - self.gridLayout_4.addWidget(self.vhash_to_vpath_in_edit, 0, 1, 1, 1) - - self.vhash_to_vpath_out_edit = QLineEdit(self.tab_utils) - self.vhash_to_vpath_out_edit.setObjectName(u"vhash_to_vpath_out_edit") - self.vhash_to_vpath_out_edit.setReadOnly(True) + self.grid_layout_4.addWidget(self.vhash_to_vpath_in_edit, 0, 1, 1, 1) - self.gridLayout_4.addWidget(self.vhash_to_vpath_out_edit, 0, 2, 1, 1) + self.tab_utils_vspacer = QSpacerItem(20, 40, QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Expanding) - self.tab_utils_vspacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.grid_layout_4.addItem(self.tab_utils_vspacer, 1, 0, 1, 1) - self.gridLayout_4.addItem(self.tab_utils_vspacer, 1, 2, 1, 1) - - self.gridLayout_4.setColumnStretch(2, 1) - self.gridLayout_4.setRowMinimumHeight(0, 28) - self.gridLayout_4.setRowMinimumHeight(1, 28) + self.grid_layout_4.setColumnStretch(2, 1) + self.grid_layout_4.setRowMinimumHeight(0, 24) self.tabs_control.addTab(self.tab_utils, "") - self.verticalLayout.addWidget(self.tabs_control) + self.vertical_layout.addWidget(self.tabs_control) - self.verticalLayout.setStretch(0, 1) + self.vertical_layout.setStretch(0, 1) self.splitter.addWidget(self.layoutWidget) self.data_view = DataViewWidget(self.splitter) self.data_view.setObjectName(u"data_view") self.splitter.addWidget(self.data_view) - self.verticalLayout_2.addWidget(self.splitter) + self.centralwidget_layout.addWidget(self.splitter) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setObjectName(u"menubar") - self.menubar.setGeometry(QRect(0, 0, 960, 26)) + self.menubar.setGeometry(QRect(0, 0, 960, 22)) self.menu_File = QMenu(self.menubar) self.menu_File.setObjectName(u"menu_File") self.menu_Tools = QMenu(self.menubar) @@ -342,7 +364,7 @@ def setupUi(self, MainWindow): # setupUi def retranslateUi(self, MainWindow): - MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None)) + MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"DECA Main Window", None)) self.action_project_new.setText(QCoreApplication.translate("MainWindow", u"&New Project...", None)) self.action_project_open.setText(QCoreApplication.translate("MainWindow", u"&Open Project...", None)) self.action_external_add.setText(QCoreApplication.translate("MainWindow", u"&Add External...", None)) @@ -370,20 +392,22 @@ def retranslateUi(self, MainWindow): self.chkbx_export_processed_mods.setText(QCoreApplication.translate("MainWindow", u"Export As Processed", None)) self.chkbx_mod_build_subset.setText(QCoreApplication.translate("MainWindow", u"Build Subset", None)) self.chkbx_export_raw_mods.setText(QCoreApplication.translate("MainWindow", u"Export Raw Files", None)) - self.bt_mod_prep.setText(QCoreApplication.translate("MainWindow", u"Extract For Modding", None)) - self.bt_mod_build.setText(QCoreApplication.translate("MainWindow", u"Build Modded Files", None)) + self.bt_mod_prep.setText(QCoreApplication.translate("MainWindow", u"PREP MOD", None)) + self.bt_mod_build.setText(QCoreApplication.translate("MainWindow", u"BUILD MOD", None)) self.chkbx_export_contents_mods.setText(QCoreApplication.translate("MainWindow", u"Export Contents", None)) self.chkbx_mod_do_not_build_archives.setText(QCoreApplication.translate("MainWindow", u"Do Not Build Archives", None)) self.tabs_control.setTabText(self.tabs_control.indexOf(self.tab_modding), QCoreApplication.translate("MainWindow", u"Modding", None)) self.chkbx_export_save_to_one_dir.setText(QCoreApplication.translate("MainWindow", u"Save To One Directory", None)) - self.chkbx_export_3d_include_skeleton.setText(QCoreApplication.translate("MainWindow", u"Include Skeleton", None)) - self.lbl_texture_format.setText(QCoreApplication.translate("MainWindow", u"Texture Format", None)) - self.bt_extract_gltf_3d.setText(QCoreApplication.translate("MainWindow", u"EXPORT 3D/GLTF2", None)) - self.cmbbx_texture_format.setItemText(0, QCoreApplication.translate("MainWindow", u"dds", None)) - self.cmbbx_texture_format.setItemText(1, QCoreApplication.translate("MainWindow", u"ddsc", None)) - self.cmbbx_texture_format.setItemText(2, QCoreApplication.translate("MainWindow", u"png", None)) + self.cmbbx_texture_format.setItemText(0, QCoreApplication.translate("MainWindow", u"DDS", None)) + self.cmbbx_texture_format.setItemText(1, QCoreApplication.translate("MainWindow", u"DDSC", None)) + self.cmbbx_texture_format.setItemText(2, QCoreApplication.translate("MainWindow", u"PNG", None)) - self.tabs_control.setTabText(self.tabs_control.indexOf(self.tab_3d_gltf2), QCoreApplication.translate("MainWindow", u"3d/GLTF2", None)) + self.lbl_texture_format.setText(QCoreApplication.translate("MainWindow", u"Texture Format", None)) + self.chkbx_export_3d_include_skeleton.setText(QCoreApplication.translate("MainWindow", u"Include Skeleton", None)) + self.bt_extract_gltf_3d.setText(QCoreApplication.translate("MainWindow", u"EXTRACT 3D/GLTF2", None)) + self.tab_32_label_1.setText("") + self.tab_32_label_2.setText("") + self.tabs_control.setTabText(self.tabs_control.indexOf(self.tab_3d_gltf2), QCoreApplication.translate("MainWindow", u"3D/GLTF2", None)) self.vhash_to_vpath_label.setText(QCoreApplication.translate("MainWindow", u"VHash -> VPath", None)) self.vhash_to_vpath_in_edit.setText(QCoreApplication.translate("MainWindow", u"0", None)) self.tabs_control.setTabText(self.tabs_control.indexOf(self.tab_utils), QCoreApplication.translate("MainWindow", u"Utils", None)) diff --git a/python/deca_gui/deca_gui/main_window.ui b/python/deca_gui/deca_gui/main_window.ui index f00b8f5..2c95d31 100644 --- a/python/deca_gui/deca_gui/main_window.ui +++ b/python/deca_gui/deca_gui/main_window.ui @@ -7,30 +7,18 @@ 0 0 960 - 603 + 600 - MainWindow + DECA Main Window - - - 7 - - - 11 - - - 11 - - - 0 - + - Qt::Horizontal + Qt::Orientation::Horizontal 7 @@ -39,7 +27,7 @@ false - + @@ -51,7 +39,7 @@ - + 1 @@ -73,6 +61,12 @@ + + + 0 + 0 + + @@ -103,7 +97,7 @@ Extract - + @@ -112,6 +106,12 @@ 0 + + + 96 + 0 + + Full @@ -169,12 +169,6 @@ EXTRACT - - - 18 - 18 - - @@ -185,18 +179,12 @@ 0 - - - 18 - 18 - - - Qt::Horizontal + Qt::Orientation::Horizontal @@ -212,7 +200,7 @@ Modding - + @@ -235,12 +223,6 @@ 0 - - - 18 - 18 - - @@ -253,26 +235,14 @@ - Extract For Modding - - - - 18 - 18 - + PREP MOD - Build Modded Files - - - - 18 - 18 - + BUILD MOD @@ -291,12 +261,6 @@ 0 - - - 18 - 18 - - @@ -309,7 +273,7 @@ - Qt::Horizontal + Qt::Orientation::Horizontal @@ -323,25 +287,9 @@ - 3d/GLTF2 + 3D/GLTF2 - - - - - - 0 - 0 - - - - - 18 - 18 - - - - + @@ -349,34 +297,7 @@ - - - - Include Skeleton - - - - - - - Texture Format - - - - - - - EXPORT 3D/GLTF2 - - - - 18 - 18 - - - - - + @@ -384,27 +305,43 @@ 0 + + + 64 + 0 + + - dds + DDS - ddsc + DDSC - png + PNG - + + + + + 0 + 0 + + + + + - Qt::Horizontal + Qt::Orientation::Horizontal @@ -414,18 +351,58 @@ - - - - Qt::Vertical + + + + + 0 + 0 + - - - 20 - 40 - + + Texture Format - + + + + + + Include Skeleton + + + + + + + EXTRACT 3D/GLTF2 + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + + + @@ -433,7 +410,14 @@ Utils - + + + + + true + + + @@ -448,17 +432,10 @@ - - - - true - - - - + - Qt::Vertical + Qt::Orientation::Vertical @@ -485,7 +462,7 @@ 0 0 960 - 26 + 22 diff --git a/resources/deca/gameinfo/thc.json b/resources/deca/gameinfo/thc.json new file mode 100644 index 0000000..a22c680 --- /dev/null +++ b/resources/deca/gameinfo/thc.json @@ -0,0 +1,70 @@ +{ + "game_id": "thc", + "exe_match": ".*theHunter.exe", + "archive_version": 10, + "file_hash_size": 4, + "oo_decompress_dll": false, + "area_prefixes": [ + "" + ], + "world_indexes": [0,1], + "world_patches": [], + "world_occluders": [], + "world_navheightfields": [], + "world_hm": [], + "world_ai": [], + "map_zooms": [0,1,2,3], + "map_max_count": 500, + "map_prefixes": [], + "unarchived_files": [], + "archive_paths": [ + "${GAME_DIR}/archives/" + ], + "mdic_ftype": "mdi", + "navmesh_ftype": "h2014", + "obc_ftype": "", + "pfs_ftype": "pfx", + "has_garcs": false, + "file_assoc": [ + { + ".ee": "sarc", + ".epe": "rtpc" + }, + { + ".bl": "sarc", + ".nl": "sarc", + ".fl": "sarc", + ".blo": "rtpc", + ".nl.mdic": "mdi", + ".fl.mdic": "mdi", + ".pfs": "pfx", + ".obc": "obc" + }, + { + ".meshc": "adf", + ".hrmeshc": "adf", + ".modelc": "adf", + ".model_xml": "txt", + ".model_deps": "txt", + ".pfxc": "pfx" + }, + { + ".ddsc": "avtx,dds", + ".hmddsc": "atx,META-NO-TYPE" + }, + { + ".fmod_sbankc": "txt", + ".fmod_bankc": "riff" + }, + { + ".swf": "gfx", + ".cfx": "gfx", + ".gfx": "gfx" + }, + { + ".gdc": "adf", + ".gsc": "adf", + ".stringlookup": "adf" + } + ] +} diff --git a/resources/deca/gameinfo/thp.json b/resources/deca/gameinfo/thp.json new file mode 100644 index 0000000..80e5121 --- /dev/null +++ b/resources/deca/gameinfo/thp.json @@ -0,0 +1,70 @@ +{ + "game_id": "thp", + "exe_match": ".*theHunterPrimal.*", + "archive_version": 11, + "file_hash_size": 4, + "oo_decompress_dll": false, + "area_prefixes": [ + "" + ], + "world_indexes": [0,1], + "world_patches": [], + "world_occluders": [], + "world_navheightfields": [], + "world_hm": [], + "world_ai": [], + "map_zooms": [0,1,2,3], + "map_max_count": 500, + "map_prefixes": [], + "unarchived_files": [], + "archive_paths": [ + "${GAME_DIR}/archives/" + ], + "mdic_ftype": "mdi", + "navmesh_ftype": "h2014", + "obc_ftype": "", + "pfs_ftype": "pfx", + "has_garcs": false, + "file_assoc": [ + { + ".ee": "sarc", + ".epe": "rtpc" + }, + { + ".bl": "sarc", + ".nl": "sarc", + ".fl": "sarc", + ".blo": "rtpc", + ".nl.mdic": "mdi", + ".fl.mdic": "mdi", + ".pfs": "pfx", + ".obc": "obc" + }, + { + ".meshc": "adf", + ".hrmeshc": "adf", + ".modelc": "adf", + ".model_xml": "txt", + ".model_deps": "txt", + ".pfxc": "pfx" + }, + { + ".ddsc": "avtx,dds", + ".hmddsc": "atx,META-NO-TYPE" + }, + { + ".fmod_sbankc": "txt", + ".fmod_bankc": "riff" + }, + { + ".swf": "gfx", + ".cfx": "gfx", + ".gfx": "gfx" + }, + { + ".gdc": "adf", + ".gsc": "adf", + ".stringlookup": "adf" + } + ] +}