Skip to content

Commit 5f899b6

Browse files
authored
Merge pull request #29 from oblivioncth/dev
Merge to master for v0.6
2 parents 154deb2 + 2e685f7 commit 5f899b6

21 files changed

+492
-117
lines changed

CMakeLists.txt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
#================= Project Setup ==========================
22

33
# CMake
4-
cmake_minimum_required(VERSION 3.23.0...3.25.0)
4+
cmake_minimum_required(VERSION 3.23.0...3.31.0)
55

66
# Project
77
# NOTE: DON'T USE TRAILING ZEROS IN VERSIONS
88
project(Stex
9-
VERSION 0.5.0.1
9+
VERSION 0.6
1010
LANGUAGES CXX
1111
DESCRIPTION "A tool to pack/unpack Klei TEX format atlases"
1212
)
1313

1414
# Get helper scripts
1515
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/FetchOBCMake.cmake)
16-
fetch_ob_cmake("v0.3.7")
16+
fetch_ob_cmake("v0.3.10")
1717

1818
# Initialize project according to standard rules
1919
include(OB/Project)
@@ -61,14 +61,18 @@ set(STEX_QX_COMPONENTS
6161
# Fetch Qx
6262
include(OB/FetchQx)
6363
ob_fetch_qx(
64-
REF "v0.5.8"
64+
REF "v0.6.3"
6565
COMPONENTS
6666
${STEX_QX_COMPONENTS}
6767
)
6868

6969
# Fetch libsquish
7070
include(OB/FetchLibSquish)
71-
ob_fetch_modern_libsquish("8a6aad970285a536170de9b3fc63735a72674561")
71+
ob_fetch_modern_libsquish("v1.15.1.3")
72+
73+
# Fetch etc2comp
74+
include(OB/FetchEtc2Comp)
75+
ob_fetch_etc2comp("v1.0.1")
7276

7377
# Process Targets
7478
set(APP_TARGET_NAME ${PROJECT_NAMESPACE_LC}_${PROJECT_NAMESPACE_LC})

app/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ ob_add_standard_executable(${APP_TARGET_NAME}
1212
command/c-compress.cpp
1313
command/c-decompress.h
1414
command/c-decompress.cpp
15+
command/c-dump.h
16+
command/c-dump.cpp
1517
command/c-pack.h
1618
command/c-pack.cpp
1719
command/c-pack.h
@@ -44,6 +46,7 @@ ob_add_standard_executable(${APP_TARGET_NAME}
4446
Qx::Io
4547
Qx::Xml
4648
libsquish::Squish
49+
Etc::Etc
4750
CONFIG STANDARD
4851
)
4952

app/src/command/c-decompress.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,18 @@ Qx::Error CDecompress::perform()
7575

7676
// Read TEX
7777
KTex tex;
78-
bool supported;
7978
QString texPath = input.absoluteFilePath();
80-
if(auto res = readTex(tex, supported, texPath); res.isFailure())
79+
if(auto res = readTex(tex, texPath); res.isFailure())
8180
{
8281
CDecompressError err(CDecompressError::CantReadTex, texPath, res.outcomeInfo());
8382
mCore.printError(NAME, err);
8483
return err;
8584
}
86-
else if(!supported)
87-
{
88-
CDecompressError err(CDecompressError::TexUnsupported, input.fileName());
89-
mCore.printError(NAME, err);
90-
return err;
91-
}
9285

9386
// Extract main image from TEX
94-
QImage image = extractImage(tex);
87+
QImage image;
88+
if(auto err = extractImage(image, tex); err.isValid())
89+
return err;
9590

9691
// Write
9792
if(auto err = writeImage(image, output.absoluteFilePath()); err.isValid())

app/src/command/c-decompress.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,15 @@ class QX_ERROR_TYPE(CDecompressError, "CDecompressError", 1214)
1616
{
1717
NoError,
1818
InvalidInput,
19-
CantReadTex,
20-
TexUnsupported
19+
CantReadTex
2120
};
2221

2322
//-Class Variables-------------------------------------------------------------
2423
private:
2524
static inline const QHash<Type, QString> ERR_STRINGS{
2625
{NoError, u""_s},
2726
{InvalidInput, u"The provided input TEX path is invalid."_s},
28-
{CantReadTex, u"Failed to read TEX."_s},
29-
{TexUnsupported, u"The input TEX is not supported."_s},
27+
{CantReadTex, u"Failed to read TEX."_s}
3028
};
3129

3230
//-Instance Variables-------------------------------------------------------------

app/src/command/c-dump.cpp

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Unit Includes
2+
#include "c-dump.h"
3+
4+
// Project Includes
5+
#include "klei/k-tex.h"
6+
#include "klei/k-tex-io.h"
7+
8+
//===============================================================================================================
9+
// CDump
10+
//===============================================================================================================
11+
12+
//-Constructor-------------------------------------------------------------
13+
//Private:
14+
CDumpError::CDumpError(Type t, const QString& s, const QString& d) :
15+
mType(t),
16+
mSpecific(s),
17+
mDetails(d)
18+
{}
19+
20+
//-Instance Functions-------------------------------------------------------------
21+
//Public:
22+
bool CDumpError::isValid() const { return mType != NoError; }
23+
QString CDumpError::specific() const { return mSpecific; }
24+
CDumpError::Type CDumpError::type() const { return mType; }
25+
26+
//Private:
27+
Qx::Severity CDumpError::deriveSeverity() const { return Qx::Critical; }
28+
quint32 CDumpError::deriveValue() const { return mType; }
29+
QString CDumpError::derivePrimary() const { return ERR_STRINGS.value(mType); }
30+
QString CDumpError::deriveSecondary() const { return mSpecific; }
31+
QString CDumpError::deriveDetails() const { return mDetails; }
32+
33+
//===============================================================================================================
34+
// CDump
35+
//===============================================================================================================
36+
37+
//-Constructor-------------------------------------------------------------
38+
//Public:
39+
CDump::CDump(Stex& coreRef) : Command(coreRef) {}
40+
41+
//-Instance Functions-------------------------------------------------------------
42+
//Private:
43+
QList<const QCommandLineOption*> CDump::options() const { return CL_OPTIONS_SPECIFIC + Command::options(); }
44+
QSet<const QCommandLineOption*> CDump::requiredOptions() const { return CL_OPTIONS_REQUIRED; }
45+
QString CDump::name() const { return NAME; }
46+
47+
Qx::IoOpReport CDump::readTex(KTex& tex, const QString& path) const
48+
{
49+
mCore.printMessage(NAME, MSG_READ_TEX);
50+
KTexReader texReader(path, tex, true);
51+
Qx::IoOpReport res = texReader.read();
52+
53+
if(!res.isFailure())
54+
mCore.printMessage(NAME, MSG_TEX_INFO.arg(tex.info(true)));
55+
56+
return res;
57+
}
58+
59+
//Public:
60+
Qx::Error CDump::perform()
61+
{
62+
mCore.printMessage(NAME, MSG_INPUT_VALIDATION);
63+
64+
// Get input
65+
QFileInfo input(mParser.value(CL_OPTION_INPUT));
66+
if(!input.exists())
67+
{
68+
CDumpError err(CDumpError::InvalidInput);
69+
mCore.printError(NAME, err);
70+
return err;
71+
}
72+
73+
// Get output
74+
QDir outputDir(
75+
mParser.isSet(CL_OPTION_OUTPUT) ?
76+
mParser.value(CL_OPTION_OUTPUT) :
77+
input.absolutePath() + '/' + input.baseName()
78+
);
79+
80+
// Read TEX
81+
KTex tex;
82+
QString texPath = input.absoluteFilePath();
83+
if(auto res = readTex(tex, texPath); res.isFailure())
84+
{
85+
CDumpError err(CDumpError::CantReadTex, texPath, res.outcomeInfo());
86+
mCore.printError(NAME, err);
87+
return err;
88+
}
89+
90+
// Check for empty TEX
91+
if(!tex.hasMipMaps())
92+
{
93+
CDumpError err(CDumpError::TexEmpty, texPath);
94+
mCore.printError(NAME, err);
95+
return err;
96+
}
97+
98+
// Make root folder
99+
if(!outputDir.mkpath("."))
100+
{
101+
CDumpError err(CDumpError::CantMakeDir, outputDir.absolutePath());
102+
mCore.printError(NAME, err);
103+
return err;
104+
}
105+
106+
// Dump
107+
for(auto i = 0; i < tex.mipMapCount(); i++)
108+
{
109+
// Get MM
110+
const auto& mm = tex.mipMaps().at(i);
111+
112+
// Save meta
113+
QFile dump(outputDir.absoluteFilePath(META_OUTPUT_TEMPLATE.arg(i)));
114+
if(auto res = Qx::writeBytesToFile(dump, mm.jsonMetadata()); res.isFailure())
115+
return res;
116+
117+
118+
// Save data
119+
dump.setFileName(outputDir.absoluteFilePath(DATA_OUTPUT_TEMPLATE.arg(i)));
120+
if(auto res = Qx::writeBytesToFile(dump, mm.imageData()); res.isFailure())
121+
return res;
122+
}
123+
124+
// Return success
125+
mCore.printMessage(NAME, MSG_SUCCESS);
126+
return Qx::Error();
127+
}

app/src/command/c-dump.h

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#ifndef CDUMP_H
2+
#define CDUMP_H
3+
4+
// Qx Includes
5+
#include <qx/io/qx-ioopreport.h>
6+
7+
// Project Includes
8+
#include "command.h"
9+
10+
class KTex;
11+
12+
class QX_ERROR_TYPE(CDumpError, "CDumpError", 1214)
13+
{
14+
friend class CDump;
15+
//-Class Enums-------------------------------------------------------------
16+
public:
17+
enum Type
18+
{
19+
NoError,
20+
InvalidInput,
21+
CantReadTex,
22+
TexEmpty,
23+
CantMakeDir
24+
};
25+
26+
//-Class Variables-------------------------------------------------------------
27+
private:
28+
static inline const QHash<Type, QString> ERR_STRINGS{
29+
{NoError, u""_s},
30+
{InvalidInput, u"The provided input TEX path is invalid."_s},
31+
{CantReadTex, u"Failed to read TEX."_s},
32+
{TexEmpty, u"The TEX contained no mip-maps."_s},
33+
{CantMakeDir, u"Failed to create output directory."_s}
34+
};
35+
36+
//-Instance Variables-------------------------------------------------------------
37+
private:
38+
Type mType;
39+
QString mSpecific;
40+
QString mDetails;
41+
42+
//-Constructor-------------------------------------------------------------
43+
private:
44+
CDumpError(Type t = NoError, const QString& s = {}, const QString& d = {});
45+
46+
//-Instance Functions-------------------------------------------------------------
47+
public:
48+
bool isValid() const;
49+
Type type() const;
50+
QString specific() const;
51+
52+
private:
53+
Qx::Severity deriveSeverity() const override;
54+
quint32 deriveValue() const override;
55+
QString derivePrimary() const override;
56+
QString deriveSecondary() const override;
57+
QString deriveDetails() const override;
58+
};
59+
60+
class CDump : public Command
61+
{
62+
//-Class Variables------------------------------------------------------------------------------------------------------
63+
private:
64+
// Messages
65+
static inline const QString MSG_READ_TEX = u"Reading TEX..."_s;
66+
static inline const QString MSG_TEX_INFO = u"TEX Info:\n%1"_s;
67+
static inline const QString MSG_EXTRACT_IMAGE = u"Extracting primary TEX image..."_s;
68+
69+
// Command line option strings
70+
static inline const QString CL_OPT_INPUT_S_NAME = u"i"_s;
71+
static inline const QString CL_OPT_INPUT_L_NAME = u"input"_s;
72+
static inline const QString CL_OPT_INPUT_DESC = u"TEX to dump."_s;
73+
74+
static inline const QString CL_OPT_OUTPUT_S_NAME = u"o"_s;
75+
static inline const QString CL_OPT_OUTPUT_L_NAME = u"output"_s;
76+
static inline const QString CL_OPT_OUTPUT_DESC = u"Path to a directory for the resultant data. Defaults to the basename of the input."_s;
77+
78+
protected:
79+
// Messages
80+
static inline const QString MSG_INPUT_VALIDATION = u"Validating input..."_s;
81+
static inline const QString MSG_SUCCESS = u"Successfully dumped TEX"_s;
82+
83+
// Output
84+
static inline const QString META_OUTPUT_TEMPLATE = u"%1-meta.json"_s;
85+
static inline const QString DATA_OUTPUT_TEMPLATE = u"%1-data.bin"_s;
86+
87+
// Command line options
88+
static inline const QCommandLineOption CL_OPTION_INPUT{{CL_OPT_INPUT_S_NAME, CL_OPT_INPUT_L_NAME}, CL_OPT_INPUT_DESC, u"input"_s}; // Takes value
89+
static inline const QCommandLineOption CL_OPTION_OUTPUT{{CL_OPT_OUTPUT_S_NAME, CL_OPT_OUTPUT_L_NAME}, CL_OPT_OUTPUT_DESC, u"output"_s}; // Takes value
90+
static inline const QList<const QCommandLineOption*> CL_OPTIONS_SPECIFIC{&CL_OPTION_INPUT, &CL_OPTION_OUTPUT};
91+
static inline const QSet<const QCommandLineOption*> CL_OPTIONS_REQUIRED{&CL_OPTION_INPUT};
92+
93+
public:
94+
// Meta
95+
static inline const QString NAME = u"dump"_s;
96+
static inline const QString DESCRIPTION = u"Dumps all image data of a TEX without converting it."_s;
97+
98+
//-Constructor----------------------------------------------------------------------------------------------------------
99+
public:
100+
CDump(Stex& coreRef);
101+
102+
//-Destructor----------------------------------------------------------------------------------------------------------
103+
public:
104+
virtual ~CDump() = default;
105+
106+
//-Instance Functions------------------------------------------------------------------------------------------------------
107+
private:
108+
QList<const QCommandLineOption*> options() const override;
109+
QSet<const QCommandLineOption*> requiredOptions() const override;
110+
QString name() const override;
111+
112+
Qx::IoOpReport readTex(KTex& tex, const QString& path) const;
113+
114+
public:
115+
Qx::Error perform() override;
116+
};
117+
REGISTER_COMMAND(CDump::NAME, CDump, CDump::DESCRIPTION);
118+
119+
#endif // CDUMP_H

app/src/command/c-pack.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ bool CPack::hasBasenameCollision(const QFileInfoList& imageFiles)
4949
{
5050
QSet<QString> baseNames;
5151

52-
for(const QFileInfo& fileInfo : qAsConst(imageFiles))
52+
for(const QFileInfo& fileInfo : std::as_const(imageFiles))
5353
{
5454
QString baseName = fileInfo.baseName();
5555

@@ -123,7 +123,7 @@ Qx::Error CPack::perform()
123123
// Generate named image map
124124
QMap<QString, QImage> namedImages;
125125

126-
for(const QFileInfo& imageInfo : qAsConst(imageFiles))
126+
for(const QFileInfo& imageInfo : std::as_const(imageFiles))
127127
{
128128
QString elementName = imageInfo.baseName();
129129
QImage image;

0 commit comments

Comments
 (0)