diff options
| author | Treeki <treeki@gmail.com> | 2010-10-07 15:56:13 +0200 | 
|---|---|---|
| committer | Treeki <treeki@gmail.com> | 2010-10-07 15:56:13 +0200 | 
| commit | 5f6dad55d75cbe146ff7fefc899a02ccd39078ba (patch) | |
| tree | 0822df14cc6d2c0329810c9ae7b4a4a638fe82b1 /lyt | |
| download | LayoutStudio-5f6dad55d75cbe146ff7fefc899a02ccd39078ba.tar.gz LayoutStudio-5f6dad55d75cbe146ff7fefc899a02ccd39078ba.zip | |
initial commit -- everything compiles except for material.cpp. the material system still needs quite a bit of work; this will come in due time
Diffstat (limited to '')
| -rw-r--r-- | lyt/binaryfile.cpp | 66 | ||||
| -rw-r--r-- | lyt/binaryfile.h | 22 | ||||
| -rw-r--r-- | lyt/binaryfilesection.cpp | 28 | ||||
| -rw-r--r-- | lyt/binaryfilesection.h | 23 | ||||
| -rw-r--r-- | lyt/bounding.cpp | 26 | ||||
| -rw-r--r-- | lyt/bounding.h | 22 | ||||
| -rw-r--r-- | lyt/common.cpp | 92 | ||||
| -rw-r--r-- | lyt/common.h | 104 | ||||
| -rw-r--r-- | lyt/directorypackage.cpp | 119 | ||||
| -rw-r--r-- | lyt/directorypackage.h | 38 | ||||
| -rw-r--r-- | lyt/group.cpp | 38 | ||||
| -rw-r--r-- | lyt/group.h | 22 | ||||
| -rw-r--r-- | lyt/layout.cpp | 223 | ||||
| -rw-r--r-- | lyt/layout.h | 67 | ||||
| -rw-r--r-- | lyt/materials/material.cpp | 127 | ||||
| -rw-r--r-- | lyt/materials/material.h | 183 | ||||
| -rw-r--r-- | lyt/materials/texmap.cpp | 41 | ||||
| -rw-r--r-- | lyt/materials/texmap.h | 25 | ||||
| -rw-r--r-- | lyt/packagebase.cpp | 5 | ||||
| -rw-r--r-- | lyt/packagebase.h | 31 | ||||
| -rw-r--r-- | lyt/pane.cpp | 87 | ||||
| -rw-r--r-- | lyt/pane.h | 58 | ||||
| -rw-r--r-- | lyt/picture.cpp | 73 | ||||
| -rw-r--r-- | lyt/picture.h | 27 | ||||
| -rw-r--r-- | lyt/textbox.cpp | 115 | ||||
| -rw-r--r-- | lyt/textbox.h | 37 | ||||
| -rw-r--r-- | lyt/window.cpp | 184 | ||||
| -rw-r--r-- | lyt/window.h | 63 | 
28 files changed, 1946 insertions, 0 deletions
| diff --git a/lyt/binaryfile.cpp b/lyt/binaryfile.cpp new file mode 100644 index 0000000..8ac2a01 --- /dev/null +++ b/lyt/binaryfile.cpp @@ -0,0 +1,66 @@ +#include "binaryfile.h" +#include "binaryfilesection.h" + +#include <QtCore/QDataStream> + +LYTBinaryFile::LYTBinaryFile(Magic magic, Version version) { +	this->magic.value = magic.value; +	this->version.value = version.value; +} + + +LYTBinaryFile::LYTBinaryFile(QByteArray data) { +	QDataStream reader(data); +	InitDataStream(reader); + +	quint16 endian, firstSectionOffset, sectionCount; +	quint32 fileSize; + +	reader >> this->magic.value; +	reader >> endian; +	reader >> this->version.value; +	reader >> fileSize; +	reader >> firstSectionOffset; +	reader >> sectionCount; + +	LYTBinaryFileSection section; + +	for (int i = 0; i < sectionCount; i++) { +		section.readFromDataStream(reader); +		this->sections.append(section); +	} +} + + +QByteArray LYTBinaryFile::pack() { +	// first off, calculate filesize for the header +	quint32 fileSize = 16; + +	foreach (LYTBinaryFileSection section, this->sections) { +		fileSize += section.writtenSize(); +	} + +	// set up other fields +	quint16 endian, firstSectionOffset; +	endian = 0xFEFF; +	firstSectionOffset = 16; + + +	// write it +	QByteArray output; +	QDataStream writer(&output, QIODevice::WriteOnly); +	InitDataStream(writer); + +	writer << this->magic.value; +	writer << endian; +	writer << this->version.value; +	writer << fileSize; +	writer << firstSectionOffset; +	writer << (quint16)this->sections.count(); + +	foreach (LYTBinaryFileSection section, this->sections) { +		section.writeToDataStream(writer); +	} + +	return output; +} diff --git a/lyt/binaryfile.h b/lyt/binaryfile.h new file mode 100644 index 0000000..6cc278c --- /dev/null +++ b/lyt/binaryfile.h @@ -0,0 +1,22 @@ +#ifndef LYTBINARYFILE_H +#define LYTBINARYFILE_H + +#include <QtCore/QList> + +#include "common.h" +#include "binaryfilesection.h" + +class LYTBinaryFile { +public: +	LYTBinaryFile(Magic magic, Version version); +	LYTBinaryFile(QByteArray data); + +	QByteArray pack(); + +	Magic magic; +	Version version; + +	QList<LYTBinaryFileSection> sections; +}; + +#endif // LYTBINARYFILE_H diff --git a/lyt/binaryfilesection.cpp b/lyt/binaryfilesection.cpp new file mode 100644 index 0000000..59dd9a1 --- /dev/null +++ b/lyt/binaryfilesection.cpp @@ -0,0 +1,28 @@ +#include "binaryfilesection.h" + +LYTBinaryFileSection::LYTBinaryFileSection() { +} + + +void LYTBinaryFileSection::writeToDataStream(QDataStream &out) { +	out << (quint32)magic.value; +	out << (quint32)data.length() + 8; +	out.writeRawData(data.constData(), data.length()); +} + +void LYTBinaryFileSection::readFromDataStream(QDataStream &in) { +	quint32 length; + +	in >> (quint32&)magic.value; +	in >> (quint32&)length; + +	char *raw = new char[length - 8]; +	in.readRawData(raw, length - 8); + +	data = QByteArray(raw, length - 8); +} + + +int LYTBinaryFileSection::writtenSize() { +	return 8 + this->data.length(); +} diff --git a/lyt/binaryfilesection.h b/lyt/binaryfilesection.h new file mode 100644 index 0000000..0d6c4f7 --- /dev/null +++ b/lyt/binaryfilesection.h @@ -0,0 +1,23 @@ +#ifndef LYTBINARYFILESECTION_H +#define LYTBINARYFILESECTION_H + +#include <QtCore/QDataStream> + +#include "common.h" + +class LYTBinaryFileSection { +public: +    LYTBinaryFileSection(); + +	Magic magic; +	QByteArray data; + +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	int writtenSize(); +}; + + + +#endif // LYTBINARYFILESECTION_H diff --git a/lyt/bounding.cpp b/lyt/bounding.cpp new file mode 100644 index 0000000..0ae793b --- /dev/null +++ b/lyt/bounding.cpp @@ -0,0 +1,26 @@ +#include "bounding.h" +#include "layout.h" +#include "common.h" + + +LYTBounding::LYTBounding(LYTLayout &layout) : LYTPane(layout) { +} + + +void LYTBounding::dumpToDebug(bool showHeading) { +	if (showHeading) +		qDebug() << "LYTBounding" << name << "@" << (void*)this; + +	LYTPane::dumpToDebug(false); +} + + + +void LYTBounding::writeToDataStream(QDataStream &out) { +	LYTPane::writeToDataStream(out); +} + + +void LYTBounding::readFromDataStream(QDataStream &in) { +	LYTPane::readFromDataStream(in); +} diff --git a/lyt/bounding.h b/lyt/bounding.h new file mode 100644 index 0000000..c742ad8 --- /dev/null +++ b/lyt/bounding.h @@ -0,0 +1,22 @@ +#ifndef LYTBOUNDING_H +#define LYTBOUNDING_H + +#include "common.h" +#include "pane.h" + +// the most useful object in LYT +// it's just a regular Pane ... with a different name. + +class LYTBounding : public LYTPane { +public: +	LYTBounding(LYTLayout &layout); + + +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(bool showHeading=true); +}; + + +#endif // LYTPICTURE_H diff --git a/lyt/common.cpp b/lyt/common.cpp new file mode 100644 index 0000000..f23e68a --- /dev/null +++ b/lyt/common.cpp @@ -0,0 +1,92 @@ +#include "common.h" + +QByteArray PadByteArray(QByteArray original, int newLength, char padWith) { +	QByteArray newArray = original; + +	if (original.length() > newLength) { +		// the original array is longer than the length desired, so truncate it +		newArray.truncate(newLength); + +	} else if (original.length() < newLength) { +		// the original array is shorter, so pad it +		int oldLength = original.length(); +		newArray.resize(newLength); + +		for (int i = oldLength; i < newLength; i++) { +			newArray[i] = '\0'; +		} +	} + +	return newArray; +} + +QStringList ReadStringList(QDataStream &in) { +	QStringList output; + +	quint16 count; +	in >> (quint16&)count; +	in.skipRawData(2); // padding + +	QVector<quint32> stringOffsets(count); + +	// save the initial offset so we can get the strings later +	// string offsets are based on the first offset entry (after the count) +	// NOT on the section offset +	qint64 savedPos = in.device()->pos(); + +	for (int i = 0; i < count; i++) { +		quint32 offset; +		in >> (quint32&)offset; +		in.skipRawData(4); // unused? + +		stringOffsets[i] = offset; +	} + +	// ok, now we can get the strings +	for (int i = 0; i < count; i++) { +		in.device()->seek(savedPos + stringOffsets[i]); + +		// how fun: no length is stored for each string, they're just zero +		// terminated. so let's try to figure it out! +		int stringLength = 0; +		char check; + +		in >> (quint8&)check; +		while (check != 0) { +			stringLength += 1; +			in >> (quint8&)check; +		} + +		// now read the string +		char *buffer = new char[stringLength]; + +		in.device()->seek(savedPos + stringOffsets[i]); +		in.readRawData(buffer, stringLength); + +		output.append(QString::fromAscii(buffer, stringLength)); + +		delete[] buffer; + + +		qDebug() << "Read string:" << output.last(); +	} + +	return output; +} + +QString ReadFixedLengthASCII(QDataStream &in, int length) { +	QByteArray readStr(length, '\0'); +	in.readRawData(readStr.data(), readStr.length()); + +	QString str = QString::fromAscii(readStr.data(), readStr.length()); +	if (str.contains(QChar('\0'))) +		str.truncate(str.indexOf(QChar('\0'))); + +	return str; +} + +void WriteFixedLengthASCII(QDataStream &out, QString str, int length) { +	QByteArray paddedStr = PadByteArray(str.toAscii(), length); +	out.writeRawData(paddedStr.constData(), paddedStr.length()); +} + diff --git a/lyt/common.h b/lyt/common.h new file mode 100644 index 0000000..72149d4 --- /dev/null +++ b/lyt/common.h @@ -0,0 +1,104 @@ +#ifndef LYTCOMMON_H +#define LYTCOMMON_H + +#include <QtGlobal> +#include <QtCore/QByteArray> +#include <QtGui/QColor> +#include <QtCore/QPointF> +#include <QtCore/QDataStream> +#include <QtCore/QStringList> +#include <QtCore/QDebug> +#include <QtCore/QVector> + +union Magic { +	char str[4]; +	quint32 value; +}; + +union Version { +	char str[2]; +	quint16 value; +}; + + + +inline quint32 BitExtract(quint32 value, int count, int start) { +	// this function relies on heavy compiler optimisation to be efficient :p +	quint32 mask = 0; +	for (int i = start; i < start+count; i++) { +		mask |= (0x80000000 >> i); +	} + +	return (value & mask) >> (32 - (start + count)); +} + + +QByteArray PadByteArray(QByteArray original, int newLength, char padWith='\0'); + +inline quint32 ColorToRGBA(QColor col) { +	return (col.red() << 24) | (col.green() << 16) | (col.blue() << 8) | (col.alpha()); +} + +inline QColor RGBAToColor(quint32 col) { +	return QColor(col >> 24, (col >> 16) & 0xFF, (col >> 8) & 0xFF, col & 0xFF); +} + +inline void ReadRGBA8Color(QColor &out, QDataStream &in) { +	quint32 col; +	in >> (quint32&)col; +	out = RGBAToColor(col); +} + +inline void WriteRGBA8Color(QColor &in, QDataStream &out) { +	out << (quint32)ColorToRGBA(in); +} + +inline void ReadS10Color(QColor &out, QDataStream &in) { +	quint16 r, g, b, a; +	in >> (quint16&)r; +	in >> (quint16&)g; +	in >> (quint16&)b; +	in >> (quint16&)a; +	out.setRgb(r, g, b, a); +} + +inline void WriteS10Color(QColor &in, QDataStream &out) { +	out << (quint16)in.red(); +	out << (quint16)in.green(); +	out << (quint16)in.blue(); +	out << (quint16)in.alpha(); +} + + + + +struct LYTTexCoords { +	QPointF coord[4]; +}; + +inline void ReadPointF(QDataStream &stream, QPointF &point) { +	float x, y; +	stream >> x; +	stream >> y; +	point.setX(x); +	point.setY(y); +} + +inline void WritePointF(QDataStream &stream, const QPointF &point) { +	stream << (float)point.x(); +	stream << (float)point.y(); +} + +inline void InitDataStream(QDataStream &stream) { +	stream.setByteOrder(QDataStream::BigEndian); +	stream.setVersion(QDataStream::Qt_4_5); +} + +QStringList ReadStringList(QDataStream &in); + +QString ReadFixedLengthASCII(QDataStream &in, int length); +void WriteFixedLengthASCII(QDataStream &out, QString str, int length); + + + +#endif // LYTCOMMON_H diff --git a/lyt/directorypackage.cpp b/lyt/directorypackage.cpp new file mode 100644 index 0000000..93e3ad8 --- /dev/null +++ b/lyt/directorypackage.cpp @@ -0,0 +1,119 @@ +#include "directorypackage.h" + +#include <QDir> + +LYTDirectoryPackage::LYTDirectoryPackage(QString path) : LYTPackageBase() { +	QDir fix_path(path); +	this->m_path = fix_path.absolutePath(); +} + + + +QStringList LYTDirectoryPackage::listSubDirIfExists(QString dirName) { +	QDir search(m_path); + +	if (search.cd(dirName)) { +		return search.entryList(); +	} + +	return QStringList(); +} + + +QByteArray LYTDirectoryPackage::getFileFromSubDirIfExists(QString dirName, QString fileName) { +	QDir search(m_path); + +	if (search.cd(dirName)) { +		QFile file(search.absoluteFilePath(fileName)); + +		if (file.open(QFile::ReadOnly)) { +			return file.readAll(); +		} +	} + +	return QByteArray(); +} + + +bool LYTDirectoryPackage::writeFileToSubDir(QString dirName, QString fileName, QByteArray data) { +	QDir search(m_path); + +	if (search.cd(dirName)) { +		QFile file(search.absoluteFilePath(fileName)); + +		if (file.open(QFile::WriteOnly)) { +			if (file.write(data) != -1) { +				return true; +			} +		} +	} + +	return false; +} + + + + +QStringList LYTDirectoryPackage::listAnims() { +	return this->listSubDirIfExists("anim"); +} + +QStringList LYTDirectoryPackage::listLayouts() { +	return this->listSubDirIfExists("blyt"); +} + +QStringList LYTDirectoryPackage::listTextures() { +	return this->listSubDirIfExists("timg"); +} + +QStringList LYTDirectoryPackage::listFonts() { +	return this->listSubDirIfExists("font"); +} + + + +QByteArray LYTDirectoryPackage::getAnim(QString name) { +	return this->getFileFromSubDirIfExists("anim", name); +} + +QByteArray LYTDirectoryPackage::getLayout(QString name) { +	return this->getFileFromSubDirIfExists("blyt", name); +} + +QByteArray LYTDirectoryPackage::getTexture(QString name) { +	return this->getFileFromSubDirIfExists("timg", name); +} + +QByteArray LYTDirectoryPackage::getFont(QString name) { +	return this->getFileFromSubDirIfExists("font", name); +} + + + +bool LYTDirectoryPackage::writeAnim(QString name, QByteArray data) { +	return this->writeFileToSubDir("anim", name, data); +} + +bool LYTDirectoryPackage::writeLayout(QString name, QByteArray data) { +	return this->writeFileToSubDir("blyt", name, data); +} + +bool LYTDirectoryPackage::writeTexture(QString name, QByteArray data) { +	return this->writeFileToSubDir("timg", name, data); +} + +bool LYTDirectoryPackage::writeFont(QString name, QByteArray data) { +	return this->writeFileToSubDir("font", name, data); +} + + + +bool LYTDirectoryPackage::savePackage() { +	// No-op since this is a directory +	return true; +} + + +QString LYTDirectoryPackage::description() { +	return m_path; +} diff --git a/lyt/directorypackage.h b/lyt/directorypackage.h new file mode 100644 index 0000000..78c6580 --- /dev/null +++ b/lyt/directorypackage.h @@ -0,0 +1,38 @@ +#ifndef LYTDIRECTORYPACKAGE_H +#define LYTDIRECTORYPACKAGE_H + +#include "packagebase.h" + +class LYTDirectoryPackage : public LYTPackageBase { +public: +	LYTDirectoryPackage(QString path); + +	QStringList listAnims(); +	QStringList listLayouts(); +	QStringList listTextures(); +	QStringList listFonts(); + +	QByteArray getAnim(QString name); +	QByteArray getLayout(QString name); +	QByteArray getTexture(QString name); +	QByteArray getFont(QString name); + +	bool writeAnim(QString name, QByteArray data); +	bool writeLayout(QString name, QByteArray data); +	bool writeTexture(QString name, QByteArray data); +	bool writeFont(QString name, QByteArray data); + +	bool savePackage(); +	QString description(); +	QString path(); + +protected: +	QStringList listSubDirIfExists(QString dirName); +	QByteArray getFileFromSubDirIfExists(QString dirName, QString fileName); +	bool writeFileToSubDir(QString dirName, QString fileName, QByteArray data); + + +	QString m_path; +}; + +#endif // LYTDIRECTORYPACKAGE_H diff --git a/lyt/group.cpp b/lyt/group.cpp new file mode 100644 index 0000000..c3a16fb --- /dev/null +++ b/lyt/group.cpp @@ -0,0 +1,38 @@ +#include "group.h" + +LYTGroup::LYTGroup() { +} + + + + +void LYTGroup::writeToDataStream(QDataStream &out) { +	WriteFixedLengthASCII(out, name, 0x10); + +	// write the contents +	out << (quint16)panes.count(); +	out.skipRawData(2); // padding + +	foreach (LYTPane *pane, panes) { +		WriteFixedLengthASCII(out, pane->name, 0x10); +	} +} + + +void LYTGroup::readFromDataStream(QDataStream &in, LYTPane &linkedPane) { +	name = ReadFixedLengthASCII(in, 0x10); +	qDebug() << "reading group" << name; + +	// read the contents +	quint16 paneCount; +	in >> (quint16&)paneCount; +	in.skipRawData(2); // padding + +	for (int i = 0; i < paneCount; i++) { +		QString paneName = ReadFixedLengthASCII(in, 0x10); + +		qDebug() << "found" << paneName << "in group" << this->name; + +		this->panes.append(linkedPane.findPaneByName(paneName, true)); +	} +} diff --git a/lyt/group.h b/lyt/group.h new file mode 100644 index 0000000..e02b710 --- /dev/null +++ b/lyt/group.h @@ -0,0 +1,22 @@ +#ifndef LYTGROUP_H +#define LYTGROUP_H + +#include "common.h" +#include "pane.h" + +#include <QtCore/QList> + +class LYTGroup { +public: +    LYTGroup(); + + +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in, LYTPane &linkedPane); + +	QString name; + +	QList<LYTPane *> panes; +}; + +#endif // LYTGROUP_H diff --git a/lyt/layout.cpp b/lyt/layout.cpp new file mode 100644 index 0000000..e501a72 --- /dev/null +++ b/lyt/layout.cpp @@ -0,0 +1,223 @@ +#include "layout.h" +#include <QtCore/QStack> +#include <QtCore/QVector> + + +LYTLayout::LYTLayout(LYTPackageBase &package) : rootPane(0), m_package(package) { +	this->clear(); +} + +LYTLayout::LYTLayout(LYTPackageBase &package, QString name) : rootPane(0), m_package(package) { +	this->loadLayoutFromPackage(name); +} + +LYTLayout::~LYTLayout() { +	this->clear(); +} + + +void LYTLayout::clear() { +	this->width = 608.0; +	this->height = 456.0; + +	this->m_fontRefs.clear(); +	this->m_textureRefs.clear(); + +	foreach (LYTMaterial *material, materials.values()) +		delete material; + +	this->materials.clear(); + +	if (this->rootPane != 0) +		delete this->rootPane; +} + + +LYTPackageBase &LYTLayout::package() const { +	return m_package; +} + + +bool LYTLayout::loadLayoutFromPackage(QString name) { +	qDebug() << "Loading layout: " << name; +	qDebug() << "From package: " << m_package.description(); + +	QStack<LYTPane *> paneStack; +	LYTPane *lastPane, *newPane; + +	bool hasGroupContainer = false; +	int groupStackID = 0; + +	QByteArray layoutData = m_package.getLayout(name); +	LYTBinaryFile file(layoutData); + +	this->clear(); + +	foreach (LYTBinaryFileSection section, file.sections) { +		// Handle every section in the file + +		qDebug("Handling %c%c%c%c", section.magic.str[3], section.magic.str[2], section.magic.str[1], section.magic.str[0]); + +		switch (section.magic.value) { +		case 'lyt1': +			this->readLyt1(section); +			break; + +		case 'txl1': +			this->readTxl1(section); +			break; + +		case 'fnl1': +			this->readFnl1(section); +			break; + +		case 'mat1': +			this->readMat1(section); +			break; + +		case 'pan1': +		case 'txt1': +		case 'pic1': +		case 'wnd1': +		case 'bnd1': +			newPane = this->createPaneObj(section); +			newPane->dumpToDebug(); + +			if (rootPane == 0) +				rootPane = newPane; + +			if (!paneStack.empty()) { +				newPane->parent = paneStack.last(); +				paneStack.last()->children.append(newPane); +			} + +			lastPane = newPane; + +			break; + +		case 'pas1': +			paneStack.push(lastPane); +			break; + +		case 'pae1': +			lastPane = paneStack.pop(); +			break; + +		case 'grp1': +			if (!hasGroupContainer) { +				// nw4r::lyt::Layout::Build actually creates a GroupContainer +				// but we just use a QList so we don't need to do that +				hasGroupContainer = true; +			} else { +				if (groupStackID == 1) { +					// create a group and add it to the list +					QDataStream in(section.data); +					InitDataStream(in); +					groups.append(new LYTGroup()); +					groups.last()->readFromDataStream(in, *this->rootPane); +				} +			} + +			break; + +		case 'grs1': +			groupStackID++; +			break; + +		case 'gre1': +			groupStackID--; +			break; +		} +	} + +	// todo: usd1 + +	return true; +} + +void LYTLayout::readLyt1(LYTBinaryFileSection §ion) { +	// initial info block containing width + height + +	QDataStream in(section.data); +	InitDataStream(in); + +	in.skipRawData(4); // unused in newer nw4r::lyt versions - TODO: add support +	in >> (float&)width; +	in >> (float&)height; + +	qDebug() << "Read lyt1 block: layout size:" << width << "x" << height; +} + +void LYTLayout::readTxl1(LYTBinaryFileSection §ion) { +	// list of texture references for this layout + +	QDataStream in(section.data); +	InitDataStream(in); +	m_textureRefs = ReadStringList(in); +} + +void LYTLayout::readFnl1(LYTBinaryFileSection §ion) { +	// list of font references for this layout + +	QDataStream in(section.data); +	InitDataStream(in); +	m_fontRefs = ReadStringList(in); +} + +void LYTLayout::readMat1(LYTBinaryFileSection §ion) { +	// the material section for the layout +	// not fun. + +	QDataStream in(section.data); +	InitDataStream(in); + +	quint16 count; +	in >> (quint16&)count; +	in.skipRawData(2); // padding + +	// create a list of every offset +	// these offsets are from the start of the section, not from +	// the first offset entry like StringLists are +	QVector<quint32> materialOffsets(count); + +	for (int i = 0; i < count; i++) { +		quint32 offset; +		in >> (quint32&)offset; +		materialOffsets[i] = offset; +	} + +	// now read each material +	for (int i = 0; i < count; i++) { +		// subtract 8 from the offset because section.data doesn't contain +		// the nw4r::ut::BinaryBlockHeader whereas these offsets do count it +		in.device()->seek(materialOffsets[i] - 8); + +		LYTMaterial *material = new LYTMaterial(*this); +		material->readFromDataStream(in); +		material->dumpToDebug(); + +		materials.insert(material->name, material); +	} +} + +LYTPane *LYTLayout::createPaneObj(LYTBinaryFileSection §ion) { +	LYTPane *pane; + +	if (section.magic.value == 'pan1') +		pane = new LYTPane(*this); +	else if (section.magic.value == 'txt1') +		pane = new LYTTextBox(*this); +	else if (section.magic.value == 'pic1') +		pane = new LYTPicture(*this); +	else if (section.magic.value == 'wnd1') +		pane = new LYTWindow(*this); +	else if (section.magic.value == 'bnd1') +		pane = new LYTBounding(*this); + +	QDataStream in(section.data); +	InitDataStream(in); + +	pane->readFromDataStream(in); + +	return pane; +} diff --git a/lyt/layout.h b/lyt/layout.h new file mode 100644 index 0000000..2af32a1 --- /dev/null +++ b/lyt/layout.h @@ -0,0 +1,67 @@ +#ifndef LYTLAYOUT_H +#define LYTLAYOUT_H + +#include "packagebase.h" +#include "materials/material.h" +#include "group.h" +#include "pane.h" +#include "textbox.h" +#include "picture.h" +#include "window.h" +#include "bounding.h" +#include "binaryfile.h" +#include "binaryfilesection.h" + +#include <QtCore/QStringList> +#include <QtCore/QMap> +#include <QtCore/QDataStream> + +class LYTTexMap; // forward declaration so it can be a friend class + +class LYTLayout { +public: +	LYTLayout(LYTPackageBase &package); +	LYTLayout(LYTPackageBase &package, QString name); +	~LYTLayout(); + +	void clear(); +	LYTPackageBase &package() const; + +	float width; +	float height; + +	QMap<QString, LYTMaterial *> materials; + +	LYTPane *rootPane; +	QList<LYTGroup *> groups; + + + +protected: +	LYTPackageBase &m_package; + +	// these are private because they are not intended for public use +	// they're only here so that LYTPane's subclasses and a few others can read +	// this info when reading/writing -- hence why they are friend classes +	QStringList m_fontRefs; +	QStringList m_textureRefs; + +	bool loadLayoutFromPackage(QString name); + +	void readLyt1(LYTBinaryFileSection §ion); +	void readTxl1(LYTBinaryFileSection §ion); +	void readFnl1(LYTBinaryFileSection §ion); +	void readMat1(LYTBinaryFileSection §ion); + +	LYTPane *createPaneObj(LYTBinaryFileSection §ion); + +	friend class LYTPane; +	friend class LYTTextBox; +	friend class LYTPicture; +	friend class LYTWindow; +	friend class LYTBounding; +	friend class LYTTexMap; + +}; + +#endif // LYTLAYOUT_H diff --git a/lyt/materials/material.cpp b/lyt/materials/material.cpp new file mode 100644 index 0000000..a23534c --- /dev/null +++ b/lyt/materials/material.cpp @@ -0,0 +1,127 @@ +#include "material.h" +#include "../layout.h" + +LYTMaterial::LYTMaterial(LYTLayout &layout) : m_layout(layout) { +} + +LYTMaterial::~LYTMaterial() { +} + +LYTLayout &LYTMaterial::layout() const { +	return m_layout; +} + + +void LYTMaterial::dumpToDebug() { +	qDebug() << "LYTMaterial" << name << "@" << (void*)this; +} + + + +void LYTMaterial::writeToDataStream(QDataStream &out) { +	WriteFixedLengthASCII(out, name, 0x14); +} + +void LYTMaterial::readFromDataStream(QDataStream &in) { +	name = ReadFixedLengthASCII(in, 0x14); + +	for (int i = 0; i < 3; i++) +		ReadS10Color(this->colours[i], in); + +	for (int i = 0; i < 4; i++) +		ReadRGBA8Color(this->tevKColour[i], in); + + +	LYTMaterialResourceNum resourceNum; +	in >> (quint32&)resourceNum.value; + +	// this is really complicated -_- +	// first off: TexMap +	texMaps.clear(); + +	for (int i = 0; i < resourceNum.getTexMapNum(); i++) { +		this->readTexMap(in); +	} + +	// TexSRT +	/*texSRTs.clear(); + +	for (int i = 0; i < resourceNum.getTexSRTNum(); i++) { +		this->readTexSRT(in); +	} + +	// TexCoordGen +	texCoordGens.clear(); + +	for (int i = 0; i < resourceNum.getTexCoordGenNum(); i++) { +		this->readTexCoordGen(in); +	} + +	// ChanCtrl +	if (resourceNum.hasChanCtrl()) { +		this->hasChanCtrl = true; +		this->readChanCtrl(in); +	} else { +		this->hasChanCtrl = false; +	} + +	// MatCol +	if (resourceNum.hasMatCol()) { +		this->hasMatCol = true; +		this->readMatCol(in); +	} else { +		this->hasMatCol = false; +	} + +	// TevSwapTable +	if (resourceNum.hasTevSwapTable()) { +		this->hasTevSwapTable = true; +		this->readTevSwapTable(in); +	} else { +		this->hasTevSwapTable = false; +	} + +	// IndTexSRT +	indTexSRTs.clear(); + +	for (int i = 0; i < resourceNum.getIndTexSRTNum(); i++) { +		this->readIndTexSRT(in); +	} + +	// IndTexStage +	indTexStages.clear(); + +	for (int i = 0; i < resourceNum.getIndTexStageNum(); i++) { +		this->readIndirectStage(in); +	} + +	// TevStage +	tevStages.clear(); + +	for (int i = 0; i < resourceNum.getTevStageNum(); i++) { +		this->readTevStage(in); +	} + +	// AlphaCompare +	if (resourceNum.hasAlphaCompare()) { +		this->hasAlphaCompare = true; +		this->readAlphaCompare(in); +	} else { +		this->hasAlphaCompare = false; +	} + +	// BlendMode +	if (resourceNum.hasBlendMode()) { +		this->hasBlendMode = true; +		this->readBlendMode(in); +	} else { +		this->hasBlendMode = false; +	}*/ +} + + + +void LYTMaterial::readTexMap(QDataStream &in) { +	this->texMaps.append(LYTTexMap()); +	this->texMaps.last().readFromDataStream(in, m_layout); +} diff --git a/lyt/materials/material.h b/lyt/materials/material.h new file mode 100644 index 0000000..73a0e57 --- /dev/null +++ b/lyt/materials/material.h @@ -0,0 +1,183 @@ +#ifndef LYTMATERIAL_H +#define LYTMATERIAL_H + +#include <QtCore/QList> +#include <QtCore/QString> +#include <QtCore/QDataStream> +#include <QtCore/QDebug> + +#include "../common.h" +#include "texmap.h" + +class LYTLayout; + + +class LYTMaterialResourceNum { +public: +	quint32 value; + +	inline  int getTexMapNum()		{ return BitExtract(value, 4, 28); } +	inline  int getTexSRTNum()		{ return BitExtract(value, 4, 24); } +	inline  int getTexCoordGenNum()	{ return BitExtract(value, 4, 20); } +	inline bool hasChanCtrl()		{ return BitExtract(value, 1, 6);  } +	inline bool hasMatCol()			{ return BitExtract(value, 1, 4);  } +	inline bool hasTevSwapTable()	{ return BitExtract(value, 1, 19); } +	inline bool hasAlphaCompare()	{ return BitExtract(value, 1, 8);  } +	inline bool hasBlendMode()		{ return BitExtract(value, 1, 7);  } +	inline  int getIndTexSRTNum()	{ return BitExtract(value, 2, 17); } +	inline  int getIndTexStageNum()	{ return BitExtract(value, 3, 14); } +	inline  int getTevStageNum()	{ return BitExtract(value, 5, 9);  } +}; + + + +class LYTTexCoordGen { +public: +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +	quint8 genType; +	quint8 src; +	quint8 mtx; +}; + +class LYTChanCtrl { +public: +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +	quint8 colourMatSrc; +	quint8 alphaMatSrc; +}; + +class LYTTevSwapMode { +public: +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +	int red; +	int green; +	int blue; +	int alpha; +}; + +class LYTTexSRT { +public: +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +	float xTrans; +	float yTrans; +	float rotate; +	float xScale; +	float yScale; +}; + +class LYTIndirectStage { +public: +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +}; + +class LYTTevStage { +public: +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +}; + +class LYTAlphaCompare { +public: +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +}; + +class LYTBlendMode { +public: +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +}; + + + + +class LYTMaterial { +public: +	LYTMaterial(LYTLayout &layout); +	~LYTMaterial(); + + +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +	LYTLayout &layout() const; + +	QString name; + +	QColor colours[3]; +	QColor tevKColour[4]; + +	QList<LYTTexMap> texMaps; +	QList<LYTTexSRT> texSRTs; +	QList<LYTTexCoordGen> texCoordGens; + +	bool hasChanCtrl; +	LYTChanCtrl chanCtrl; + +	bool hasMatCol; +	QColor matCol; + +	bool hasTevSwapTable; +	LYTTevSwapMode tevSwapTable; + +	bool hasAlphaCompare; +	LYTAlphaCompare alphaCompare; + +	bool hasBlendMode; +	LYTBlendMode blendMode; + +	QList<LYTIndirectStage> indTexStages; +	QList<LYTTexSRT> indTexSRTs; + +	QList<LYTTevStage> tevStages; + + + +protected: +	LYTLayout &m_layout; + +	void readTexMap(QDataStream &in); +	void readTexSRT(QDataStream &in); +	void readTexCoordGen(QDataStream &in); +	void readChanCtrl(QDataStream &in); +	void readMatCol(QDataStream &in); +	void readTevSwapTable(QDataStream &in); +	void readAlphaCompare(QDataStream &in); +	void readBlendMode(QDataStream &in); +	void readIndirectStage(QDataStream &in); +	void readIndTexSRT(QDataStream &in); +	void readTevStage(QDataStream &in); +}; + +#endif // LYTMATERIAL_H diff --git a/lyt/materials/texmap.cpp b/lyt/materials/texmap.cpp new file mode 100644 index 0000000..1bb416b --- /dev/null +++ b/lyt/materials/texmap.cpp @@ -0,0 +1,41 @@ +#include "texmap.h" +#include "../layout.h" + +LYTTexMap::LYTTexMap() { +} + +void LYTTexMap::dumpToDebug() { +	qDebug() << "LYTTexMap @" << (void*)this << ":" << textureName; +	qDebug() << "- wrap_s:" << wrap_s << "- wrap_t:" << wrap_t; +	qDebug() << "- mag_filter:" << mag_filter << "- min_filter:" << min_filter; +} + + +void LYTTexMap::writeToDataStream(QDataStream &out, LYTLayout &layout) { +	quint16 texNum = layout.m_textureRefs.indexOf(textureName); +	out << (quint16)texNum; + +	quint8 var1, var2; +	var1 = wrap_s | (((min_filter + 7) & 7) << 2); +	var2 = wrap_t | (((mag_filter + 1) & 1) << 2); +	out << (quint8)var1; +	out << (quint8)var2; +} + + +void LYTTexMap::readFromDataStream(QDataStream &in, LYTLayout &layout) { +	quint16 texNum; +	in >> (quint16&)texNum; + +	textureName = layout.m_textureRefs[texNum]; + +	quint8 var1, var2; +	in >> (quint8&)var1; +	in >> (quint8&)var2; + +	wrap_s = BitExtract(var1, 2, 30); +	wrap_t = BitExtract(var2, 2, 30); + +	min_filter = (BitExtract(var1, 3, 27) + 1) & 7; +	mag_filter = (BitExtract(var2, 1, 29) + 1) & 1; +} diff --git a/lyt/materials/texmap.h b/lyt/materials/texmap.h new file mode 100644 index 0000000..5f74478 --- /dev/null +++ b/lyt/materials/texmap.h @@ -0,0 +1,25 @@ +#ifndef LYTTEXMAP_H +#define LYTTEXMAP_H + +#include "../common.h" +#include <QtCore/QDataStream> + +class LYTLayout; // forward declaration + +class LYTTexMap { +public: +	LYTTexMap(); + +	void writeToDataStream(QDataStream &out, LYTLayout &layout); +	void readFromDataStream(QDataStream &in, LYTLayout &layout); + +	void dumpToDebug(); + +	QString textureName; +	int wrap_s; +	int wrap_t; +	int mag_filter; +	int min_filter; +}; + +#endif // LYTTEXMAP_H diff --git a/lyt/packagebase.cpp b/lyt/packagebase.cpp new file mode 100644 index 0000000..f1da14b --- /dev/null +++ b/lyt/packagebase.cpp @@ -0,0 +1,5 @@ +#include "packagebase.h" + +LYTPackageBase::LYTPackageBase() { +	// do nothing +} diff --git a/lyt/packagebase.h b/lyt/packagebase.h new file mode 100644 index 0000000..7f04cea --- /dev/null +++ b/lyt/packagebase.h @@ -0,0 +1,31 @@ +#ifndef LYTPACKAGEBASE_H +#define LYTPACKAGEBASE_H + +#include <QStringList> +#include <QByteArray> + + +class LYTPackageBase { +public: +	LYTPackageBase(); + +	virtual QStringList listAnims() = 0; +	virtual QStringList listLayouts() = 0; +	virtual QStringList listTextures() = 0; +	virtual QStringList listFonts() = 0; + +	virtual QByteArray getAnim(QString name) = 0; +	virtual QByteArray getLayout(QString name) = 0; +	virtual QByteArray getTexture(QString name) = 0; +	virtual QByteArray getFont(QString name) = 0; + +	virtual bool writeAnim(QString name, QByteArray data) = 0; +	virtual bool writeLayout(QString name, QByteArray data) = 0; +	virtual bool writeTexture(QString name, QByteArray data) = 0; +	virtual bool writeFont(QString name, QByteArray data) = 0; + +	virtual bool savePackage() = 0; +	virtual QString description() = 0; +}; + +#endif // LYTPACKAGEBASE_H diff --git a/lyt/pane.cpp b/lyt/pane.cpp new file mode 100644 index 0000000..9cf3617 --- /dev/null +++ b/lyt/pane.cpp @@ -0,0 +1,87 @@ +#include "pane.h" +#include "layout.h" + +LYTPane::LYTPane(LYTLayout &layout) : m_layout(layout) { +	this->parent = 0; +} + +LYTPane::~LYTPane() { +	foreach (LYTPane *ptr, this->children) +		delete ptr; +} + +LYTPane *LYTPane::findPaneByName(QString name, bool recursive) { +	foreach (LYTPane *pane, this->children) { +		if (pane->name == name) +			return pane; + +		if (recursive) { +			LYTPane *tryThis = pane->findPaneByName(name, recursive); +			if (tryThis != 0) +				return tryThis; +		} +	} + +	return 0; +} + +LYTLayout &LYTPane::layout() const { +	return m_layout; +} + + +void LYTPane::dumpToDebug(bool showHeading) { +	if (showHeading) +		qDebug() << "LYTPane" << name << "@" << (void*)this; + +	qDebug() << "- Translation:" << xTrans << "," << yTrans << "," << zTrans; +	qDebug() << "- Rotation:" << xRot << "," << yRot << "," << zRot; +	qDebug() << "- Scale:" << xScale << "," << yScale; +	qDebug() << "- Size:" << width << "x" << height; +	qDebug() << "- Flags:" << flags << "- Origin:" << origin; +	qDebug() << "- Alpha:" << alpha << "- Userdata:" << userdata; +} + + + +void LYTPane::writeToDataStream(QDataStream &out) { +	out << (quint8)flags; +	out << (quint8)origin; +	out << (quint8)alpha; +	out.skipRawData(1); // padding + +	WriteFixedLengthASCII(out, name, 0x10); +	WriteFixedLengthASCII(out, userdata, 8); + +	out << (float)xTrans; +	out << (float)yTrans; +	out << (float)zTrans; +	out << (float)xRot; +	out << (float)yRot; +	out << (float)zRot; +	out << (float)xScale; +	out << (float)yScale; +	out << (float)width; +	out << (float)height; +} + +void LYTPane::readFromDataStream(QDataStream &in) { +	in >> (quint8&)flags; +	in >> (quint8&)origin; +	in >> (quint8&)alpha; +	in.skipRawData(1); // padding + +	name = ReadFixedLengthASCII(in, 0x10); +	userdata = ReadFixedLengthASCII(in, 8); + +	in >> (float&)xTrans; +	in >> (float&)yTrans; +	in >> (float&)zTrans; +	in >> (float&)xRot; +	in >> (float&)yRot; +	in >> (float&)zRot; +	in >> (float&)xScale; +	in >> (float&)yScale; +	in >> (float&)width; +	in >> (float&)height; +} diff --git a/lyt/pane.h b/lyt/pane.h new file mode 100644 index 0000000..7b2f37b --- /dev/null +++ b/lyt/pane.h @@ -0,0 +1,58 @@ +#ifndef LYTPANE_H +#define LYTPANE_H + +#include <QtCore/QList> +#include <QtCore/QString> +#include <QtCore/QDataStream> +#include <QtCore/QDebug> + +#include "common.h" + +class LYTLayout; + +class LYTPane { +public: +	LYTPane(LYTLayout &layout); +	virtual ~LYTPane(); + + +	virtual void writeToDataStream(QDataStream &out); +	virtual void readFromDataStream(QDataStream &in); + +	virtual void dumpToDebug(bool showHeading=true); + +	LYTPane *findPaneByName(QString name, bool recursive); + +	LYTLayout &layout() const; + +	LYTPane *parent; +	QList<LYTPane *> children; + +	quint8 flags; +	quint8 origin; +	quint8 alpha; + +	QString name; +	QString userdata; + +	float xTrans; +	float yTrans; +	float zTrans; + +	float xRot; +	float yRot; +	float zRot; + +	float xScale; +	float yScale; + +	float width; +	float height; + +protected: +	LYTLayout &m_layout; +}; + + + +#endif // LYTPANE_H diff --git a/lyt/picture.cpp b/lyt/picture.cpp new file mode 100644 index 0000000..33b2461 --- /dev/null +++ b/lyt/picture.cpp @@ -0,0 +1,73 @@ +#include "picture.h" +#include "layout.h" +#include "common.h" + + +LYTPicture::LYTPicture(LYTLayout &layout) : LYTPane(layout) { +} + + +void LYTPicture::dumpToDebug(bool showHeading) { +	if (showHeading) +		qDebug() << "LYTPicture" << name << "@" << (void*)this; + +	LYTPane::dumpToDebug(false); + +	qDebug() << "- Vertex Colours:" << vtxColours[0] << "-" << vtxColours[1]; +	qDebug() << "                 " << vtxColours[2] << "-" << vtxColours[3]; +	qDebug() << "- Material:" << materialName; +	qDebug() << "- Tex Coords:" << texCoords.count(); + +	foreach (LYTTexCoords texCoord, texCoords) { +		qDebug() << "----" << texCoord.coord[0] << "-" << texCoord.coord[1] << "-" << texCoord.coord[2] << "-" << texCoord.coord[3]; +	} +} + + + + +void LYTPicture::writeToDataStream(QDataStream &out) { +	LYTPane::writeToDataStream(out); + +	for (int i = 0; i < 4; i++) +		WriteRGBA8Color(vtxColours[i], out); + +	// calculate the material number +	int materialNum = m_layout.materials.keys().indexOf(materialName); +	out << (quint16)materialNum; + +	// write texcoords +	out << (quint8)texCoords.count(); +	out.skipRawData(1); // padding + +	foreach (LYTTexCoords texCoord, texCoords) { +		for (int i = 0; i < 4; i++) +			WritePointF(out, texCoord.coord[i]); +	} +} + + +void LYTPicture::readFromDataStream(QDataStream &in) { +	LYTPane::readFromDataStream(in); + +	for (int i = 0; i < 4; i++) +		ReadRGBA8Color(vtxColours[i], in); + +	// read the material name +	quint16 materialNum; +	in >> (quint16&)materialNum; + +	materialName = m_layout.materials.keys().at(materialNum); + +	// read texcoords +	quint8 texCoordNum; +	in >> (quint8&)texCoordNum; +	in.skipRawData(1); // padding + +	texCoords.resize(texCoordNum); + +	foreach (LYTTexCoords texCoord, texCoords) { +		for (int i = 0; i < 4; i++) +			ReadPointF(in, texCoord.coord[i]); +	} +} diff --git a/lyt/picture.h b/lyt/picture.h new file mode 100644 index 0000000..8242c34 --- /dev/null +++ b/lyt/picture.h @@ -0,0 +1,27 @@ +#ifndef LYTPICTURE_H +#define LYTPICTURE_H + +#include <QtGui/QColor> +#include <QtCore/QVector> + +#include "common.h" +#include "pane.h" + +class LYTPicture : public LYTPane { +public: +	LYTPicture(LYTLayout &layout); + + +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(bool showHeading=true); + +	QColor vtxColours[4]; +	QString materialName; + +	QVector<LYTTexCoords> texCoords; +}; + + +#endif // LYTPICTURE_H diff --git a/lyt/textbox.cpp b/lyt/textbox.cpp new file mode 100644 index 0000000..06aed4e --- /dev/null +++ b/lyt/textbox.cpp @@ -0,0 +1,115 @@ +#include "textbox.h" +#include "layout.h" +#include "common.h" + + +LYTTextBox::LYTTextBox(LYTLayout &layout) : LYTPane(layout) { +} + + +void LYTTextBox::dumpToDebug(bool showHeading) { +	if (showHeading) +		qDebug() << "LYTTextBox" << name << "@" << (void*)this; + +	LYTPane::dumpToDebug(false); + +	qDebug() << "- Text:" << text; +	qDebug() << "- Buffer Length:" << bufferLength; +	qDebug() << "- Material:" << materialName << "- Font:" << fontName; +	qDebug() << "- Alignment:" << alignment << "- Alignment Override:" << alignmentOverride; +	qDebug() << "- Colours:" << colour1 << "--" << colour2; +	qDebug() << "- Font Size:" << fontSizeX << "x" << fontSizeY; +	qDebug() << "- Char Space:" << charSpace << "- Line Space:" << lineSpace; +} + + + +void LYTTextBox::writeToDataStream(QDataStream &out) { +	LYTPane::writeToDataStream(out); + +	// lengths are stored in bytes (including zero terminator) not characters +	out << (quint16)((bufferLength + 1) * 2); +	out << (quint16)((text.length() + 1) * 2); + +	// calculate the material and font numbers +	int materialNum = m_layout.materials.keys().indexOf(materialName); +	int fontNum = m_layout.m_fontRefs.indexOf(fontName); + +	out << (quint16)materialNum; +	out << (quint16)fontNum; + +	out << (quint8)alignment; +	out << (quint8)alignmentOverride; + +	out.skipRawData(2); // padding + +	out << (quint32)0x74; // fixed offset to textbox contents + +	WriteRGBA8Color(colour1, out); +	WriteRGBA8Color(colour2, out); + +	out << (float)fontSizeX; +	out << (float)fontSizeY; +	out << (float)charSpace; +	out << (float)lineSpace; + +	// write the textbox contents +	const ushort *convertedText = text.utf16(); +	for (int i = 0; i < text.length(); i++) +		out << (quint16)convertedText[i]; +} + + +void LYTTextBox::readFromDataStream(QDataStream &in) { +	qint64 saveStartPos = in.device()->pos(); + +	LYTPane::readFromDataStream(in); + +	// the lengths are stored in bytes (not characters) and count the +	// zero terminator, and strings are UTF-16 (I think) so we need +	// to take it off here +	in >> (quint16&)bufferLength; +	bufferLength >>= 1; +	bufferLength--; + +	quint16 stringLength; +	in >> (quint16&)stringLength; +	stringLength >>= 1; +	stringLength--; + +	// read the material and font names +	quint16 materialNum, fontNum; +	in >> (quint16&)materialNum; +	in >> (quint16&)fontNum; + +	materialName = m_layout.materials.keys().at(materialNum); +	fontName = m_layout.m_fontRefs.at(fontNum); + +	in >> (quint8&)alignment; +	in >> (quint8&)alignmentOverride; + +	in.skipRawData(2); // padding + +	quint32 stringOffset; +	in >> (quint32&)stringOffset; + +	ReadRGBA8Color(colour1, in); +	ReadRGBA8Color(colour2, in); + +	in >> (float&)fontSizeX; +	in >> (float&)fontSizeY; +	in >> (float&)charSpace; +	in >> (float&)lineSpace; + +	// read the textbox contents +	// subtract 8 to account for BinaryBlockHeader or whatever it's called +	in.device()->seek(saveStartPos + stringOffset - 8); + +	ushort *rawText = new ushort[stringLength]; + +	for (int i = 0; i < stringLength; i++) +		in >> (quint16&)rawText[i]; + +	text.setUtf16(rawText, stringLength); +	delete[] rawText; +} diff --git a/lyt/textbox.h b/lyt/textbox.h new file mode 100644 index 0000000..de1020d --- /dev/null +++ b/lyt/textbox.h @@ -0,0 +1,37 @@ +#ifndef LYTTEXTBOX_H +#define LYTTEXTBOX_H + +#include <QtGui/QColor> + +#include "pane.h" + +class LYTTextBox : public LYTPane { +public: +	LYTTextBox(LYTLayout &layout); + + +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(bool showHeading=true); + +	quint16 bufferLength; +	QString text; + +	QString materialName; +	QString fontName; + +	quint8 alignment; +	quint8 alignmentOverride; + +	QColor colour1; +	QColor colour2; + +	float fontSizeX; +	float fontSizeY; +	float charSpace; +	float lineSpace; +}; + + +#endif // LYTTEXTBOX_H diff --git a/lyt/window.cpp b/lyt/window.cpp new file mode 100644 index 0000000..0430229 --- /dev/null +++ b/lyt/window.cpp @@ -0,0 +1,184 @@ +#include "window.h" +#include "layout.h" +#include "common.h" + + +LYTWindowFrame::LYTWindowFrame(LYTWindow &window) : m_window(window) { +} + +void LYTWindowFrame::writeToDataStream(QDataStream &out) { +	// calculate the material number +	int materialNum = m_window.m_layout.materials.keys().indexOf(materialName); +	out << (quint16)materialNum; + +	out << (quint8)type; +	out.skipRawData(1); // padding +} + +void LYTWindowFrame::readFromDataStream(QDataStream &in) { +	// read the material name +	quint16 materialNum; +	in >> (quint16&)materialNum; + +	materialName = m_window.m_layout.materials.keys().at(materialNum); + +	in >> (quint8&)type; +	in.skipRawData(1); // padding +} + +void LYTWindowFrame::dumpToDebug() { +	qDebug() << "LYTWindowFrame @" << (void*)this << "- type:" << type << "- material:" << materialName; +} + + + +LYTWindow::LYTWindow(LYTLayout &layout) : LYTPane(layout) { +} + +LYTWindow::~LYTWindow() { +	foreach (LYTWindowFrame *frame, frames) +		delete frame; +} + + + +// all of this needs to be done + +void LYTWindow::dumpToDebug(bool showHeading) { +	if (showHeading) +		qDebug() << "LYTWindow" << name << "@" << (void*)this; + +	LYTPane::dumpToDebug(false); + +	qDebug() << "- Content VtxColours:" << contentVtxColours[0] << "-" << contentVtxColours[1]; +	qDebug() << "                     " << contentVtxColours[2] << "-" << contentVtxColours[3]; +	qDebug() << "- Content Material:" << contentMaterialName; +	qDebug() << "- Content Tex Coords:" << contentTexCoords.count(); + +	foreach (LYTTexCoords texCoord, contentTexCoords) { +		qDebug() << "----" << texCoord.coord[0] << "-" << texCoord.coord[1] << "-" << texCoord.coord[2] << "-" << texCoord.coord[3]; +	} + +	qDebug() << "- Content Overflow: Left" << contentOverflowLeft << "- Right" << contentOverflowRight; +	qDebug() << "                    Top" << contentOverflowTop << "- Bottom" << contentOverflowBottom; + +	qDebug() << "- Frames:" << frames.count(); + +	foreach (LYTWindowFrame *frame, frames) { +		frame->dumpToDebug(); +	} +} + + + +void LYTWindow::writeToDataStream(QDataStream &out) { +	LYTPane::writeToDataStream(out); + +	out << (float)contentOverflowLeft; +	out << (float)contentOverflowRight; +	out << (float)contentOverflowTop; +	out << (float)contentOverflowBottom; + +	out << (quint8)frames.count(); +	out.skipRawData(3); // padding + +	out << (quint32)0x68; // offset to content struct +	out << (quint32)(0x7C + (contentTexCoords.count()*0x20)); // offset to frame offset list + +	for (int i = 0; i < 4; i++) +		WriteRGBA8Color(contentVtxColours[i], out); + +	// calculate the material number +	int materialNum = m_layout.materials.keys().indexOf(contentMaterialName); +	out << (quint16)materialNum; + +	// write texcoords +	out << (quint8)contentTexCoords.count(); +	out.skipRawData(1); // padding + +	foreach (LYTTexCoords texCoord, contentTexCoords) { +		for (int i = 0; i < 4; i++) +			WritePointF(out, texCoord.coord[i]); +	} + +	// write frame offsets +	quint32 frameOffset = 0x7C; // end of fixed-size part of content struct +	frameOffset += (contentTexCoords.count() * 0x20); // end of content struct +	frameOffset += (frames.count() * 4); // end of offset list + +	for (int i = 0; i < frames.count(); i++) { +		out << (quint32)frameOffset; +		frameOffset += 4; // size of frame struct +	} + +	// now write frames +	foreach (LYTWindowFrame *frame, frames) { +		frame->writeToDataStream(out); +	} +} + + +void LYTWindow::readFromDataStream(QDataStream &in) { +	qint64 startPos = in.device()->pos(); + +	LYTPane::readFromDataStream(in); + +	in >> (float&)contentOverflowLeft; +	in >> (float&)contentOverflowRight; +	in >> (float&)contentOverflowTop; +	in >> (float&)contentOverflowBottom; + +	quint8 frameCount; +	in >> (quint8&)frameCount; +	in.skipRawData(3); // padding + +	quint32 contentOffset, frameListOffset; +	in >> (quint32&)contentOffset; +	in >> (quint32&)frameListOffset; + +	// read content struct +	// subtract 8 from the offset because section.data doesn't contain +	// the nw4r::ut::BinaryBlockHeader whereas these offsets do count it +	in.device()->seek(startPos + contentOffset - 8); + +	for (int i = 0; i < 4; i++) +		ReadRGBA8Color(contentVtxColours[i], in); + +	// read the material name +	quint16 materialNum; +	in >> (quint16&)materialNum; + +	contentMaterialName = m_layout.materials.keys().at(materialNum); + +	// read texcoords +	quint8 texCoordNum; +	in >> (quint8&)texCoordNum; +	in.skipRawData(1); // padding + +	contentTexCoords.resize(texCoordNum); + +	foreach (LYTTexCoords texCoord, contentTexCoords) { +		for (int i = 0; i < 4; i++) +			ReadPointF(in, texCoord.coord[i]); +	} + +	// read frame offset list +	// subtract 8 from the offset once again +	in.device()->seek(startPos + frameListOffset - 8); + +	QVector<quint32> frameOffsets(frameCount); + +	for (int i = 0; i < frameCount; i++) { +		quint32 offset; +		in >> (quint32&)offset; +		frameOffsets[i] = offset; +	} + +	// now read each frame +	for (int i = 0; i < frameCount; i++) { +		in.device()->seek(frameOffsets[i] - 8); + +		frames.append(new LYTWindowFrame(*this)); +		frames.last()->readFromDataStream(in); +	} +} diff --git a/lyt/window.h b/lyt/window.h new file mode 100644 index 0000000..dbd3c1a --- /dev/null +++ b/lyt/window.h @@ -0,0 +1,63 @@ +#ifndef LYTWINDOW_H +#define LYTWINDOW_H + +#include <QtGui/QColor> +#include <QtCore/QVector> + +#include "common.h" +#include "pane.h" + + +class LYTWindow; // forward declaration + +class LYTWindowFrame { +public: +	LYTWindowFrame(LYTWindow &window); + + +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(); + +	quint8 type; // 0-5; controls texture flipping; must investigate this more +	QString materialName; + +protected: +	LYTWindow &m_window; +}; + + +class LYTWindow : public LYTPane { +public: +	LYTWindow(LYTLayout &layout); +	~LYTWindow(); + + +	void writeToDataStream(QDataStream &out); +	void readFromDataStream(QDataStream &in); + +	void dumpToDebug(bool showHeading=true); + + +	float contentOverflowLeft; +	float contentOverflowRight; +	float contentOverflowTop; +	float contentOverflowBottom; + +	QColor contentVtxColours[4]; +	QString contentMaterialName; +	QVector<LYTTexCoords> contentTexCoords; + +	QList<LYTWindowFrame *> frames; + + +protected: +	void writeContentInfo(QDataStream &out); +	void readContentInfo(QDataStream &in); + +	friend class LYTWindowFrame; +}; + + +#endif // LYTWINDOW_H | 
