mirror of
https://github.com/TheGameratorT/NitroModel_ConverterGUI.git
synced 2025-06-18 21:55:37 -04:00
Add initial project files.
This commit is contained in:
parent
65fd5434bf
commit
6e1362e520
52
NitroModel_ConverterGUI.pro
Normal file
52
NitroModel_ConverterGUI.pro
Normal file
@ -0,0 +1,52 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2019-11-17T15:33:43
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = NitroModel_ConverterGUI
|
||||
TEMPLATE = app
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which has been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
# You can also make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
CONFIG += c++11
|
||||
CONFIG += static
|
||||
|
||||
RC_FILE = app.rc
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
modeltonsbmd.cpp \
|
||||
texturednsbmdtonsbtx.cpp \
|
||||
texturetonsbtx.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
modeltonsbmd.h \
|
||||
texturednsbmdtonsbtx.h \
|
||||
texturetonsbtx.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
modeltonsbmd.ui \
|
||||
texturednsbmdtonsbtx.ui \
|
||||
texturetonsbtx.ui
|
||||
|
||||
# Default rules for deployment.
|
||||
qnx: target.path = /tmp/$${TARGET}/bin
|
||||
else: unix:!android: target.path = /opt/$${TARGET}/bin
|
||||
!isEmpty(target.path): INSTALLS += target
|
11
main.cpp
Normal file
11
main.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
30
mainwindow.cpp
Normal file
30
mainwindow.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include "modeltonsbmd.h"
|
||||
#include "texturetonsbtx.h"
|
||||
#include "texturednsbmdtonsbtx.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ModelToNSBMD *ModelToNSBMD_Window = new ModelToNSBMD;
|
||||
ui->ModelToNSBMD_mdiArea->addSubWindow(ModelToNSBMD_Window, Qt::FramelessWindowHint | Qt::MSWindowsFixedSizeDialogHint);
|
||||
ModelToNSBMD_Window->showMaximized();
|
||||
|
||||
/*TextureToNSBTX *TextureToNSBTX_Window = new TextureToNSBTX;
|
||||
ui->TextureToNSBTX_mdiArea->addSubWindow(TextureToNSBTX_Window, Qt::FramelessWindowHint | Qt::MSWindowsFixedSizeDialogHint);
|
||||
TextureToNSBTX_Window->showMaximized();*/
|
||||
|
||||
TexturedNSBMDToNSBTX *TexturedNSBMDToNSBTX_Window = new TexturedNSBMDToNSBTX;
|
||||
ui->TexturedNSBMDToNSBTX_mdiArea->addSubWindow(TexturedNSBMDToNSBTX_Window, Qt::FramelessWindowHint | Qt::MSWindowsFixedSizeDialogHint);
|
||||
TexturedNSBMDToNSBTX_Window->showMaximized();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
22
mainwindow.h
Normal file
22
mainwindow.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
68
mainwindow.ui
Normal file
68
mainwindow.ui
Normal file
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>600</width>
|
||||
<height>430</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>470</width>
|
||||
<height>430</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Nitro Model Converter GUI</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Model to NSBMD</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QMdiArea" name="ModelToNSBMD_mdiArea"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Texture to NSBTX</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QMdiArea" name="TextureToNSBTX_mdiArea"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>Textured NSBMD → NSBTX</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QMdiArea" name="TexturedNSBMDToNSBTX_mdiArea"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
202
modeltonsbmd.cpp
Normal file
202
modeltonsbmd.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
#include "modeltonsbmd.h"
|
||||
#include "ui_modeltonsbmd.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
static QString exeDir;
|
||||
|
||||
ModelToNSBMD::ModelToNSBMD(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::ModelToNSBMD)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
exeDir = QApplication::applicationDirPath();
|
||||
}
|
||||
|
||||
ModelToNSBMD::~ModelToNSBMD()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ModelToNSBMD::on_searchPath1_pb_clicked()
|
||||
{
|
||||
static QString lastDirSelected = QDir::homePath();
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Model File"), lastDirSelected, ""/*tr("Model Files (*.png *.jpg *.bmp)")*/);
|
||||
if(fileName == "")
|
||||
return;
|
||||
lastDirSelected = fileName;
|
||||
ui->path1_le->setText(fileName);
|
||||
}
|
||||
|
||||
void ModelToNSBMD::on_seachPath2_pb_clicked()
|
||||
{
|
||||
static QString lastDirSelected = QDir::homePath();
|
||||
if(lastDirSelected == QDir::homePath() && ui->path1_le->text() != "")
|
||||
lastDirSelected = ui->path1_le->text().split('.')[0];
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save NSBMD File"), lastDirSelected, tr("NSBMD File (*.nsbmd)"));
|
||||
if(fileName == "")
|
||||
return;
|
||||
lastDirSelected = fileName;
|
||||
ui->path2_le->setText(fileName);
|
||||
}
|
||||
|
||||
//CONVERSION STUFF AHEAD
|
||||
|
||||
void ModelToNSBMD::printToConsole(const QString &text)
|
||||
{
|
||||
ui->console_tb->setTextColor(QColor(0, 255, 0));
|
||||
QString textToLower = text.toLower();
|
||||
|
||||
if(textToLower.contains("error"))
|
||||
ui->console_tb->setTextColor(QColor("red"));
|
||||
else if(textToLower.contains("warning"))
|
||||
ui->console_tb->setTextColor(QColor("yellow"));
|
||||
|
||||
ui->console_tb->append(text);
|
||||
}
|
||||
|
||||
void ModelToNSBMD::printAppOutputToConsole(QProcess* process)
|
||||
{
|
||||
QString line;
|
||||
do
|
||||
{
|
||||
line = process->readLine();
|
||||
if (line.toLower().contains("error:") || line.toLower().contains("warning:")) {
|
||||
if(!(line.endsWith('.') or line.endsWith('!'))) {
|
||||
printToConsole(line.trimmed() + '!');
|
||||
}
|
||||
else {
|
||||
printToConsole(line.trimmed());
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!line.isNull());
|
||||
}
|
||||
|
||||
void ModelToNSBMD::on_convert_pb_clicked()
|
||||
{
|
||||
ui->console_tb->clear();
|
||||
|
||||
QString sourcePath = ui->path1_le->text();
|
||||
QString destinationPath = ui->path2_le->text();
|
||||
|
||||
bool AtLeast1PathWasNotSpecified = false;
|
||||
if(sourcePath == "")
|
||||
{
|
||||
AtLeast1PathWasNotSpecified = true;
|
||||
printToConsole("Error: No source model file was specified!");
|
||||
}
|
||||
if(destinationPath == "")
|
||||
{
|
||||
AtLeast1PathWasNotSpecified = true;
|
||||
printToConsole("Error: No destination NSBMD path was specified!");
|
||||
}
|
||||
if(AtLeast1PathWasNotSpecified)
|
||||
return;
|
||||
|
||||
bool IsSourceFileIMD = false;
|
||||
if(sourcePath.endsWith(".imd", Qt::CaseInsensitive))
|
||||
IsSourceFileIMD = true;
|
||||
|
||||
QDir tempDir(exeDir + "/temp");
|
||||
if(!IsSourceFileIMD)
|
||||
{
|
||||
printToConsole("Cleaning temp folder...");
|
||||
|
||||
tempDir.removeRecursively();
|
||||
while(tempDir.exists()) {} //Wait for temp folder to be deleted
|
||||
QDir().mkdir(tempDir.path());
|
||||
|
||||
printToConsole("Starting conversion to IMD...");
|
||||
|
||||
QProcess* ass2imd = new QProcess();
|
||||
ass2imd->setProgram(exeDir + "/bin/ass2imd/AssToImd");
|
||||
ass2imd->setArguments({sourcePath, "-o", tempDir.path() + "/temp.imd"});
|
||||
ass2imd->start();
|
||||
if(ass2imd->state() == QProcess::NotRunning)
|
||||
{
|
||||
printToConsole("Error: AssToImd failed to start or could not be found!");
|
||||
return;
|
||||
}
|
||||
connect(ass2imd, &QProcess::readyRead, [=](){ printAppOutputToConsole(ass2imd); });
|
||||
ass2imd->waitForFinished(-1);
|
||||
|
||||
if(QFile::exists(tempDir.path() + "/temp.imd"))
|
||||
printToConsole("Success: IMD generated successfully!");
|
||||
else
|
||||
{
|
||||
printToConsole("Error: IMD failed to generate!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QString sourcePath2 = tempDir.path() + "/temp.imd";
|
||||
if(IsSourceFileIMD)
|
||||
sourcePath2 = sourcePath;
|
||||
|
||||
printToConsole("Starting conversion to NSBMD...");
|
||||
|
||||
QProcess* imd2nsbmd = new QProcess();
|
||||
imd2nsbmd->setProgram(exeDir + "/bin/imd2nsbmd/imd2nsbmd");
|
||||
imd2nsbmd->setArguments({sourcePath2, "-o", destinationPath});
|
||||
imd2nsbmd->start();
|
||||
if(imd2nsbmd->state() == QProcess::NotRunning)
|
||||
{
|
||||
printToConsole("Error: imd2nsbmd failed to start or could not be found!");
|
||||
return;
|
||||
}
|
||||
connect(imd2nsbmd, &QProcess::readyRead, [=](){ printAppOutputToConsole(imd2nsbmd); });
|
||||
imd2nsbmd->waitForFinished(-1);
|
||||
|
||||
if(QFile::exists(destinationPath))
|
||||
{
|
||||
QFile file(destinationPath);
|
||||
if (!file.open(QIODevice::ReadWrite)) return;
|
||||
QByteArray fileBytes = file.readAll();
|
||||
|
||||
QString name = ui->path3_le->text();
|
||||
if(name == "")
|
||||
name = "unnamed";
|
||||
//Mess crap because QByteArray replace is stupid and a fixed replace size can't be set
|
||||
QByteArray nameBytes = name.toUtf8();
|
||||
nameBytes.resize(16);
|
||||
for(int i = name.length(); i < 16; i++)
|
||||
nameBytes[i] = 0;
|
||||
//Mess end lol
|
||||
|
||||
//Set NSBMD name
|
||||
fileBytes.replace(0x38, 16, nameBytes);
|
||||
file.resize(0);
|
||||
file.write(fileBytes);
|
||||
file.close();
|
||||
|
||||
printToConsole("Success: NSBMD generated successfully!");
|
||||
}
|
||||
else
|
||||
{
|
||||
printToConsole("Error: NSBMD failed to generate!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelToNSBMD::on_path3_le_textChanged()
|
||||
{
|
||||
int cursorPos = ui->path3_le->cursorPosition();
|
||||
QString newText;
|
||||
|
||||
for(QChar character : ui->path3_le->text())
|
||||
{
|
||||
if(!((character >= 'A' && character <= 'Z') ||
|
||||
(character >= 'a' && character <= 'z') ||
|
||||
(character >= '0' && character <= '9')))
|
||||
{
|
||||
character = '_';
|
||||
}
|
||||
newText.append(character);
|
||||
}
|
||||
|
||||
ui->path3_le->setText(newText);
|
||||
ui->path3_le->setCursorPosition(cursorPos);
|
||||
}
|
35
modeltonsbmd.h
Normal file
35
modeltonsbmd.h
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef MODELTONSBMD_H
|
||||
#define MODELTONSBMD_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QProcess>
|
||||
|
||||
namespace Ui {
|
||||
class ModelToNSBMD;
|
||||
}
|
||||
|
||||
class ModelToNSBMD : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ModelToNSBMD(QWidget *parent = nullptr);
|
||||
~ModelToNSBMD();
|
||||
|
||||
private slots:
|
||||
void on_searchPath1_pb_clicked();
|
||||
|
||||
void on_seachPath2_pb_clicked();
|
||||
|
||||
void on_convert_pb_clicked();
|
||||
|
||||
void on_path3_le_textChanged();
|
||||
|
||||
private:
|
||||
Ui::ModelToNSBMD *ui;
|
||||
|
||||
void printToConsole(const QString &text);
|
||||
void printAppOutputToConsole(QProcess* process);
|
||||
};
|
||||
|
||||
#endif // MODELTONSBMD_H
|
173
modeltonsbmd.ui
Normal file
173
modeltonsbmd.ui
Normal file
@ -0,0 +1,173 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ModelToNSBMD</class>
|
||||
<widget class="QMainWindow" name="ModelToNSBMD">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>605</width>
|
||||
<height>410</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QMainWindow {
|
||||
background-color: rgb(255, 255, 255);
|
||||
}</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>95</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>95</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="searchPath1_pb">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="text1_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Source Model File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="text2_label">
|
||||
<property name="text">
|
||||
<string>Destination NSBMD File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="path1_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="path2_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="seachPath2_pb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="text3_label">
|
||||
<property name="text">
|
||||
<string>NSBMD Name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="path3_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>16</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="console_tb">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(0, 0, 0);</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="convert_pb">
|
||||
<property name="text">
|
||||
<string>Convert And Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>path1_le</tabstop>
|
||||
<tabstop>searchPath1_pb</tabstop>
|
||||
<tabstop>path2_le</tabstop>
|
||||
<tabstop>seachPath2_pb</tabstop>
|
||||
<tabstop>console_tb</tabstop>
|
||||
<tabstop>convert_pb</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
169
texturednsbmdtonsbtx.cpp
Normal file
169
texturednsbmdtonsbtx.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
#include "texturednsbmdtonsbtx.h"
|
||||
#include "ui_texturednsbmdtonsbtx.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
TexturedNSBMDToNSBTX::TexturedNSBMDToNSBTX(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::TexturedNSBMDToNSBTX)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
TexturedNSBMDToNSBTX::~TexturedNSBMDToNSBTX()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TexturedNSBMDToNSBTX::on_searchPath1_pb_clicked()
|
||||
{
|
||||
static QString lastDirSelected = QDir::homePath();
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open NSBMD File"), lastDirSelected, tr("NSBMD File (*.nsbmd)"));
|
||||
if(fileName == "")
|
||||
return;
|
||||
lastDirSelected = fileName;
|
||||
ui->path1_le->setText(fileName);
|
||||
}
|
||||
|
||||
void TexturedNSBMDToNSBTX::on_seachPath2_pb_clicked()
|
||||
{
|
||||
static QString lastDirSelected = QDir::homePath();
|
||||
if(lastDirSelected == QDir::homePath() && ui->path1_le->text() != "")
|
||||
lastDirSelected = ui->path1_le->text().split('.')[0];
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save NSBTX File"), lastDirSelected, tr("NSBTX File (*.nsbtx)"));
|
||||
if(fileName == "")
|
||||
return;
|
||||
lastDirSelected = fileName;
|
||||
ui->path2_le->setText(fileName);
|
||||
}
|
||||
|
||||
//CONVERSION STUFF AHEAD
|
||||
|
||||
void TexturedNSBMDToNSBTX::printToConsole(const QString &text)
|
||||
{
|
||||
ui->console_tb->setTextColor(QColor(0, 255, 0));
|
||||
QString textToLower = text.toLower();
|
||||
|
||||
if(textToLower.contains("error"))
|
||||
ui->console_tb->setTextColor(QColor("red"));
|
||||
else if(textToLower.contains("warning"))
|
||||
ui->console_tb->setTextColor(QColor("yellow"));
|
||||
|
||||
ui->console_tb->append(text);
|
||||
}
|
||||
|
||||
void TexturedNSBMDToNSBTX::on_convert_pb_clicked()
|
||||
{
|
||||
ui->console_tb->clear();
|
||||
|
||||
QString sourcePath = ui->path1_le->text();
|
||||
QString destinationPath = ui->path2_le->text();
|
||||
|
||||
bool AtLeast1PathWasNotSpecified = false;
|
||||
if(sourcePath == "")
|
||||
{
|
||||
AtLeast1PathWasNotSpecified = true;
|
||||
printToConsole("Error: No source NSBMD file was specified!");
|
||||
}
|
||||
if(destinationPath == "")
|
||||
{
|
||||
AtLeast1PathWasNotSpecified = true;
|
||||
printToConsole("Error: No destination NSBTX path was specified!");
|
||||
}
|
||||
if(AtLeast1PathWasNotSpecified)
|
||||
return;
|
||||
|
||||
QFile sourceFile(sourcePath);
|
||||
if (!sourceFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
printToConsole("Error: Could not access file for reading, check if it's being used by another program or if the program has permission to do so on that directory.");
|
||||
return;
|
||||
}
|
||||
QByteArray nsbmdData = sourceFile.readAll();
|
||||
sourceFile.close();
|
||||
|
||||
printToConsole("Checking for NSBMD file magic (BMD0) match...");
|
||||
if(!(nsbmdData[0] == 'B' &&
|
||||
nsbmdData[1] == 'M' &&
|
||||
nsbmdData[2] == 'D' &&
|
||||
nsbmdData[3] == '0'))
|
||||
{
|
||||
printToConsole("Error: Invalid NSBMD file specified.\nError details: File magic didn't match.");
|
||||
return;
|
||||
}
|
||||
printToConsole("Match found, proceeding with conversion!");
|
||||
|
||||
printToConsole("Searching for model (MDL0) block offset...");
|
||||
//Find block offsets
|
||||
int MLD0_blockOffset = 0;
|
||||
for (int i = 0; i < nsbmdData.size(); i++)
|
||||
{
|
||||
if(nsbmdData[i+0] == 'M' &&
|
||||
nsbmdData[i+1] == 'D' &&
|
||||
nsbmdData[i+2] == 'L' &&
|
||||
nsbmdData[i+3] == '0')
|
||||
{
|
||||
MLD0_blockOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(MLD0_blockOffset == 0)
|
||||
printToConsole("Error: No model data to remove could be found in the NSBMD.\nError details: MDL0 block doesn't exist!");
|
||||
else
|
||||
printToConsole("Found model (MDL0) block!");
|
||||
|
||||
printToConsole("Searching for texture (TEX0) block offset...");
|
||||
int TEX0_blockOffset = 0;
|
||||
for (int i = 0; i < nsbmdData.size(); i++)
|
||||
{
|
||||
if(nsbmdData[i+0] == 'T' &&
|
||||
nsbmdData[i+1] == 'E' &&
|
||||
nsbmdData[i+2] == 'X' &&
|
||||
nsbmdData[i+3] == '0')
|
||||
{
|
||||
TEX0_blockOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(TEX0_blockOffset == 0)
|
||||
printToConsole("Error: No texture data to keep could be found in the NSBMD.\nError details: TEX0 block doesn't exist!");
|
||||
else
|
||||
printToConsole("Found texture (TEX0) block!");
|
||||
|
||||
//Remove MDL0 block
|
||||
printToConsole("Removing model block (MDL0)...");
|
||||
int MLD0_blockLen = TEX0_blockOffset - MLD0_blockOffset;
|
||||
nsbmdData.remove(MLD0_blockOffset, MLD0_blockLen);
|
||||
|
||||
//Update name in header
|
||||
printToConsole("Updating header file magic...");
|
||||
nsbmdData.replace(0, 4, "BTX0");
|
||||
|
||||
//Update file size in header (remove MDL0 block length from it)
|
||||
printToConsole("Updating header file size...");
|
||||
quint32* nsbmdDataAsUint = reinterpret_cast<quint32*>(nsbmdData.data());
|
||||
nsbmdDataAsUint[2] -= static_cast<quint32>(MLD0_blockLen);
|
||||
|
||||
//Update section count
|
||||
printToConsole("Updating header section count...");
|
||||
quint16* nsbmdDataAsUshort = reinterpret_cast<quint16*>(nsbmdData.data());
|
||||
nsbmdDataAsUshort[7] -= 1;
|
||||
|
||||
//Save NSBTX file
|
||||
printToConsole("Saving...");
|
||||
QFile destinationFile(destinationPath);
|
||||
if (!destinationFile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
printToConsole("Error: Could not access file for writing, check if it's being used by another program or if the program has permission to do so on that directory.");
|
||||
return;
|
||||
}
|
||||
destinationFile.write(nsbmdData);
|
||||
destinationFile.close();
|
||||
|
||||
if(QFile::exists(destinationPath))
|
||||
printToConsole("Success: NSBTX converted and saved successfully!");
|
||||
}
|
31
texturednsbmdtonsbtx.h
Normal file
31
texturednsbmdtonsbtx.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef TEXTUREDNSBMDTONSBTX_H
|
||||
#define TEXTUREDNSBMDTONSBTX_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
namespace Ui {
|
||||
class TexturedNSBMDToNSBTX;
|
||||
}
|
||||
|
||||
class TexturedNSBMDToNSBTX : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TexturedNSBMDToNSBTX(QWidget *parent = nullptr);
|
||||
~TexturedNSBMDToNSBTX();
|
||||
|
||||
private slots:
|
||||
void on_searchPath1_pb_clicked();
|
||||
|
||||
void on_seachPath2_pb_clicked();
|
||||
|
||||
void on_convert_pb_clicked();
|
||||
|
||||
private:
|
||||
Ui::TexturedNSBMDToNSBTX *ui;
|
||||
|
||||
void printToConsole(const QString &text);
|
||||
};
|
||||
|
||||
#endif // TEXTUREDNSBMDTONSBTX_H
|
153
texturednsbmdtonsbtx.ui
Normal file
153
texturednsbmdtonsbtx.ui
Normal file
@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TexturedNSBMDToNSBTX</class>
|
||||
<widget class="QMainWindow" name="TexturedNSBMDToNSBTX">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>605</width>
|
||||
<height>410</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QMainWindow {
|
||||
background-color: rgb(255, 255, 255);
|
||||
}</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>63</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>63</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="path1_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="text1_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Source NSBMD File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="path2_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="text2_label">
|
||||
<property name="text">
|
||||
<string>Destination NSBTX File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="seachPath2_pb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="searchPath1_pb">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="console_tb">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(0, 0, 0);</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="convert_pb">
|
||||
<property name="text">
|
||||
<string>Convert And Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>path1_le</tabstop>
|
||||
<tabstop>searchPath1_pb</tabstop>
|
||||
<tabstop>path2_le</tabstop>
|
||||
<tabstop>seachPath2_pb</tabstop>
|
||||
<tabstop>console_tb</tabstop>
|
||||
<tabstop>convert_pb</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
80
texturetonsbtx.cpp
Normal file
80
texturetonsbtx.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "texturetonsbtx.h"
|
||||
#include "ui_texturetonsbtx.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
TextureToNSBTX::TextureToNSBTX(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::TextureToNSBTX)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
TextureToNSBTX::~TextureToNSBTX()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TextureToNSBTX::on_searchPath1_pb_clicked()
|
||||
{
|
||||
static QString lastDirSelected = QDir::homePath();
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Texture File"), lastDirSelected, ""/*tr("Model Files (*.png *.jpg *.bmp)")*/);
|
||||
if(fileName == "")
|
||||
return;
|
||||
lastDirSelected = fileName;
|
||||
ui->path1_le->setText(fileName);
|
||||
}
|
||||
|
||||
void TextureToNSBTX::on_seachPath2_pb_clicked()
|
||||
{
|
||||
static QString lastDirSelected = QDir::homePath();
|
||||
if(lastDirSelected == QDir::homePath() && ui->path1_le->text() != "")
|
||||
lastDirSelected = ui->path1_le->text().split('.')[0];
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Save NSBTX File"), lastDirSelected, tr("NSBTX File (*.nsbtx)"));
|
||||
if(fileName == "")
|
||||
return;
|
||||
lastDirSelected = fileName;
|
||||
ui->path2_le->setText(fileName);
|
||||
}
|
||||
|
||||
//CONVERSION STUFF AHEAD
|
||||
|
||||
void TextureToNSBTX::printToConsole(const QString &text)
|
||||
{
|
||||
ui->console_tb->setTextColor(QColor(0, 255, 0));
|
||||
QString textToLower = text.toLower();
|
||||
|
||||
if(textToLower.contains("error"))
|
||||
ui->console_tb->setTextColor(QColor("red"));
|
||||
else if(textToLower.contains("warning"))
|
||||
ui->console_tb->setTextColor(QColor("yellow"));
|
||||
|
||||
ui->console_tb->append(text);
|
||||
}
|
||||
|
||||
void TextureToNSBTX::printAppOutputToConsole(QProcess* process)
|
||||
{
|
||||
QString line;
|
||||
do
|
||||
{
|
||||
line = process->readLine();
|
||||
if (line.toLower().contains("error:") || line.toLower().contains("warning:")) {
|
||||
if(!(line.endsWith('.') or line.endsWith('!'))) {
|
||||
printToConsole(line.trimmed() + '!');
|
||||
}
|
||||
else {
|
||||
printToConsole(line.trimmed());
|
||||
}
|
||||
}
|
||||
}
|
||||
while (!line.isNull());
|
||||
}
|
||||
|
||||
void TextureToNSBTX::on_convert_pb_clicked()
|
||||
{
|
||||
ui->console_tb->clear();
|
||||
|
||||
|
||||
}
|
33
texturetonsbtx.h
Normal file
33
texturetonsbtx.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef TEXTURETONSBTX_H
|
||||
#define TEXTURETONSBTX_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QProcess>
|
||||
|
||||
namespace Ui {
|
||||
class TextureToNSBTX;
|
||||
}
|
||||
|
||||
class TextureToNSBTX : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TextureToNSBTX(QWidget *parent = nullptr);
|
||||
~TextureToNSBTX();
|
||||
|
||||
private slots:
|
||||
void on_searchPath1_pb_clicked();
|
||||
|
||||
void on_seachPath2_pb_clicked();
|
||||
|
||||
void on_convert_pb_clicked();
|
||||
|
||||
private:
|
||||
Ui::TextureToNSBTX *ui;
|
||||
|
||||
void printToConsole(const QString &text);
|
||||
void printAppOutputToConsole(QProcess* process);
|
||||
};
|
||||
|
||||
#endif // TEXTURETONSBTX_H
|
153
texturetonsbtx.ui
Normal file
153
texturetonsbtx.ui
Normal file
@ -0,0 +1,153 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TextureToNSBTX</class>
|
||||
<widget class="QMainWindow" name="TextureToNSBTX">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>605</width>
|
||||
<height>410</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QMainWindow {
|
||||
background-color: rgb(255, 255, 255);
|
||||
}</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>63</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>63</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="path1_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="text1_label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Source Texture File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="path2_le">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="text2_label">
|
||||
<property name="text">
|
||||
<string>Destination NSBTX File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="seachPath2_pb">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QPushButton" name="searchPath1_pb">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="console_tb">
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(0, 0, 0);</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="convert_pb">
|
||||
<property name="text">
|
||||
<string>Convert And Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>path1_le</tabstop>
|
||||
<tabstop>searchPath1_pb</tabstop>
|
||||
<tabstop>path2_le</tabstop>
|
||||
<tabstop>seachPath2_pb</tabstop>
|
||||
<tabstop>console_tb</tabstop>
|
||||
<tabstop>convert_pb</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in New Issue
Block a user