Added a system to override primitives and updated the stud logos to use it.

This commit is contained in:
Leonardo Zide 2021-01-18 15:23:13 -08:00
parent cbfd2ce4bc
commit a8d757c0c4
9 changed files with 101 additions and 104 deletions

View file

@ -60,9 +60,7 @@ void lcPiecesLibrary::Unload()
delete PieceIt.second;
mPieces.clear();
for (const auto& PrimitiveIt : mPrimitives)
delete PrimitiveIt.second;
mPrimitives.clear();
mSources.clear();
for (lcTexture* Texture : mTextures)
delete Texture;
@ -259,11 +257,6 @@ bool lcPiecesLibrary::Load(const QString& LibraryPath, bool ShowProgress)
if (!mZipFiles[static_cast<int>(lcZipFileType::Official)]->ExtractFile("ldraw/ldconfig.ldr", ColorFile) || !lcLoadColorFile(ColorFile))
lcLoadDefaultColors();
std::unique_ptr<lcDiskFile> PrimitivesFile(new lcDiskFile(":/resources/primitives.zip"));
if (PrimitivesFile->Open(QIODevice::ReadOnly))
OpenArchive(std::move(PrimitivesFile), lcZipFileType::Primitives);
mLibraryDir = QFileInfo(LibraryPath).absoluteDir();
QString UnofficialFileName = mLibraryDir.absoluteFilePath(QLatin1String("ldrawunf.zip"));
@ -290,22 +283,34 @@ bool lcPiecesLibrary::Load(const QString& LibraryPath, bool ShowProgress)
lcLoadDefaultColors();
}
}
std::unique_ptr<lcDiskFile> PrimitivesFile(new lcDiskFile(":/resources/primitives.zip"));
if (PrimitivesFile->Open(QIODevice::ReadOnly))
OpenArchive(std::move(PrimitivesFile), lcZipFileType::Primitives);
}
else
return false;
}
UpdateStudLogoSource();
lcLoadDefaultCategories();
lcSynthInit();
return true;
}
void lcPiecesLibrary::UpdateStudLogoSource()
{
if (!mSources.empty() && mSources.front()->Type == lcLibrarySourceType::StudLogo)
mSources.erase(mSources.begin());
mZipFiles[static_cast<int>(lcZipFileType::StudLogo)].reset();
if (!mStudLogo)
return;
std::unique_ptr<lcDiskFile> StudLogoFile(new lcDiskFile(QString(":/resources/studlogo%1.zip").arg(QString::number(mStudLogo))));
if (StudLogoFile->Open(QIODevice::ReadOnly))
OpenArchive(std::move(StudLogoFile), lcZipFileType::StudLogo);
}
bool lcPiecesLibrary::OpenArchive(const QString& FileName, lcZipFileType ZipFileType)
{
std::unique_ptr<lcDiskFile> File(new lcDiskFile(FileName));
@ -323,6 +328,9 @@ bool lcPiecesLibrary::OpenArchive(std::unique_ptr<lcFile> File, lcZipFileType Zi
if (!ZipFile->OpenRead(std::move(File)))
return false;
std::unique_ptr<lcLibrarySource> Source(new lcLibrarySource);
Source->Type = ZipFileType != lcZipFileType::StudLogo ? lcLibrarySourceType::Library : lcLibrarySourceType::StudLogo;
for (int FileIdx = 0; FileIdx < ZipFile->mFiles.GetSize(); FileIdx++)
{
lcZipFileInfo& FileInfo = ZipFile->mFiles[FileIdx];
@ -398,29 +406,18 @@ bool lcPiecesLibrary::OpenArchive(std::unique_ptr<lcFile> File, lcZipFileType Zi
Info->SetZipFile(ZipFileType, FileIdx);
}
else
{
lcLibraryPrimitive* Primitive = FindPrimitive(Name);
if (!Primitive)
mPrimitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NameBuffer), ZipFileType, FileIdx, false, true);
else
Primitive->SetZipFile(ZipFileType, FileIdx);
}
Source->Primitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NameBuffer), ZipFileType, FileIdx, false, true);
}
else if (!memcmp(Name, "P/", 2))
{
Name += 2;
lcLibraryPrimitive* Primitive = FindPrimitive(Name);
if (!Primitive)
mPrimitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NameBuffer), ZipFileType, FileIdx, (memcmp(Name, "STU", 3) == 0), false);
else
Primitive->SetZipFile(ZipFileType, FileIdx);
Source->Primitives[Name] = new lcLibraryPrimitive(QString(), FileInfo.file_name + (Name - NameBuffer), ZipFileType, FileIdx, (memcmp(Name, "STU", 3) == 0), false);
}
}
mZipFiles[static_cast<int>(ZipFileType)] = std::move(ZipFile);
mSources.insert(mSources.begin(), std::move(Source));
return true;
}
@ -500,6 +497,9 @@ bool lcPiecesLibrary::OpenDirectory(const QDir& LibraryDir, bool ShowProgress)
for (unsigned int BaseFolderIdx = 0; BaseFolderIdx < LC_ARRAY_COUNT(BaseFolders); BaseFolderIdx++)
{
std::unique_ptr<lcLibrarySource> Source(new lcLibrarySource);
Source->Type = lcLibrarySourceType::Library;
const char* PrimitiveDirectories[] = { "p/", "parts/s/" };
bool SubFileDirectories[] = { false, false, true };
QDir BaseDir(LibraryDir.absoluteFilePath(QLatin1String(BaseFolders[BaseFolderIdx])));
@ -545,9 +545,11 @@ bool lcPiecesLibrary::OpenDirectory(const QDir& LibraryDir, bool ShowProgress)
mHasUnofficial = true;
const bool SubFile = SubFileDirectories[DirectoryIdx];
mPrimitives[Name] = new lcLibraryPrimitive(std::move(FileName), strchr(FileString, '/') + 1, lcZipFileType::Count, 0, !SubFile && (memcmp(Name, "STU", 3) == 0), SubFile);
Source->Primitives[Name] = new lcLibraryPrimitive(std::move(FileName), strchr(FileString, '/') + 1, lcZipFileType::Count, 0, !SubFile && (memcmp(Name, "STU", 3) == 0), SubFile);
}
}
mSources.push_back(std::move(Source));
}
for (unsigned int BaseFolderIdx = 0; BaseFolderIdx < LC_ARRAY_COUNT(BaseFolders); BaseFolderIdx++)
@ -1513,21 +1515,26 @@ void lcPiecesLibrary::UploadTextures(lcContext* Context)
bool lcPiecesLibrary::SupportsStudLogo() const
{
return mZipFiles[static_cast<int>(lcZipFileType::Primitives)] != nullptr || mHasUnofficial;
return true;
}
void lcPiecesLibrary::SetStudLogo(int StudLogo, bool Reload)
{
mStudLogo = StudLogo;
UpdateStudLogoSource();
mLoadMutex.lock();
for (const auto& PrimitiveIt : mPrimitives)
for (const std::unique_ptr<lcLibrarySource>& Source : mSources)
{
for (const auto& PrimitiveIt : Source->Primitives)
{
lcLibraryPrimitive* Primitive = PrimitiveIt.second;
if (Primitive->mMeshData.mHasLogoStud)
Primitive->Unload();
}
}
mLoadMutex.unlock();
@ -1553,27 +1560,26 @@ void lcPiecesLibrary::SetStudLogo(int StudLogo, bool Reload)
}
}
bool lcPiecesLibrary::GetStudLogoFile(lcMemFile& PrimFile, int StudLogo, bool OpenStud)
bool lcPiecesLibrary::IsPrimitive(const char* Name) const
{
if (!StudLogo || !SupportsStudLogo())
return false;
const QLatin1String LineEnding("\r\n");
QByteArray FileData;
QTextStream TextStream(&FileData);
TextStream << (OpenStud ? QLatin1String("0 Stud Open") : QLatin1String("0 Stud")) << LineEnding;
TextStream << (OpenStud ? QLatin1String("0 Name: stud2.dat") : QLatin1String("0 Name: stud.dat")) << LineEnding;
TextStream << QLatin1String("0 Author: James Jessiman") << LineEnding;
TextStream << QLatin1String("0 !LDRAW_ORG Primitive") << LineEnding;
TextStream << QLatin1String("0 BFC CERTIFY CCW") << LineEnding;
TextStream << QString("1 16 0 0 0 1 0 0 0 1 0 0 0 1 stud%1-logo%2.dat").arg(OpenStud ? "2" : QString(), StudLogo > 1 ? QString::number(StudLogo) : QString()) << LineEnding;
TextStream.flush();
PrimFile.WriteBuffer(FileData.constData(), size_t(FileData.size()));
PrimFile.Seek(0, SEEK_SET);
for (const std::unique_ptr<lcLibrarySource>& Source : mSources)
if (Source->Primitives.find(Name) != Source->Primitives.end())
return true;
return false;
}
lcLibraryPrimitive* lcPiecesLibrary::FindPrimitive(const char* Name) const
{
for (const std::unique_ptr<lcLibrarySource>& Source : mSources)
{
const auto PrimitiveIt = Source->Primitives.find(Name);
if (PrimitiveIt != Source->Primitives.end())
return PrimitiveIt->second;
}
return nullptr;
}
bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
@ -1596,8 +1602,6 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
lcMeshLoader MeshLoader(Primitive->mMeshData, true, nullptr, false);
bool SetStudLogo = false;
if (mZipFiles[static_cast<int>(lcZipFileType::Official)])
{
lcLibraryPrimitive* LowPrimitive = nullptr;
@ -1606,27 +1610,20 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
if (Primitive->mStud)
{
const bool OpenStud = !strcmp(Primitive->mName,"stud2.dat");
if (OpenStud || !strcmp(Primitive->mName,"stud.dat"))
{
if (!strcmp(Primitive->mName, "stud.dat") || !strcmp(Primitive->mName, "stud2.dat"))
Primitive->mMeshData.mHasLogoStud = true;
if (mStudLogo)
SetStudLogo = GetStudLogoFile(PrimFile, mStudLogo, OpenStud);
}
if (!SetStudLogo && strncmp(Primitive->mName, "8/", 2)) // todo: this is currently the only place that uses mName so use mFileName instead. this should also be done for the loose file libraries.
else if (strncmp(Primitive->mName, "8/", 2)) // todo: this is currently the only place that uses mName so use mFileName instead. this should also be done for the loose file libraries.
{
char Name[LC_PIECE_NAME_LEN];
strcpy(Name, "8/");
strcat(Name, Primitive->mName);
strupr(Name);
LowPrimitive = FindPrimitive(Name);
LowPrimitive = FindPrimitive(Name); // todo: low primitives don't work with studlogo, because the low stud gets added as shared
}
}
if (!SetStudLogo && !mZipFiles[static_cast<int>(Primitive->mZipFileType)]->ExtractFile(Primitive->mZipFileIndex, PrimFile))
if (!mZipFiles[static_cast<int>(Primitive->mZipFileType)]->ExtractFile(Primitive->mZipFileIndex, PrimFile))
return false;
if (!LowPrimitive)
@ -1650,23 +1647,10 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
{
if (Primitive->mStud)
{
const bool OpenStud = !strcmp(Primitive->mName,"stud2.dat");
if (OpenStud || !strcmp(Primitive->mName,"stud.dat"))
{
if (!strcmp(Primitive->mName,"stud.dat") || !strcmp(Primitive->mName, "stud2.dat"))
Primitive->mMeshData.mHasLogoStud = true;
if (mStudLogo)
{
lcMemFile PrimFile;
if (GetStudLogoFile(PrimFile, mStudLogo, OpenStud))
SetStudLogo = MeshLoader.LoadMesh(PrimFile, LC_MESHDATA_SHARED);
}
}
}
if (!SetStudLogo)
{
if (Primitive->mZipFileType == lcZipFileType::Count)
{
lcDiskFile PrimFile(Primitive->mFileName);
@ -1685,7 +1669,6 @@ bool lcPiecesLibrary::LoadPrimitive(lcLibraryPrimitive* Primitive)
return false;
}
}
}
mLoadMutex.lock();
Primitive->mState = lcPrimitiveState::Loaded;

View file

@ -14,7 +14,7 @@ enum class lcZipFileType
{
Official,
Unofficial,
Primitives,
StudLogo,
Count
};
@ -70,6 +70,24 @@ public:
lcLibraryMeshData mMeshData;
};
enum class lcLibrarySourceType
{
Library,
StudLogo
};
struct lcLibrarySource
{
~lcLibrarySource()
{
for (const auto& PrimitiveIt : Primitives)
delete PrimitiveIt.second;
}
lcLibrarySourceType Type;
std::map<std::string, lcLibraryPrimitive*> Primitives;
};
class lcPiecesLibrary : public QObject
{
Q_OBJECT
@ -115,17 +133,8 @@ public:
void GetPrimitiveFile(lcLibraryPrimitive* Primitive, std::function<void(lcFile& File)> Callback);
void GetPieceFile(const char* FileName, std::function<void(lcFile& File)> Callback);
bool IsPrimitive(const char* Name) const
{
return mPrimitives.find(Name) != mPrimitives.end();
}
lcLibraryPrimitive* FindPrimitive(const char* Name) const
{
const auto PrimitiveIt = mPrimitives.find(Name);
return PrimitiveIt != mPrimitives.end() ? PrimitiveIt->second : nullptr;
}
bool IsPrimitive(const char* Name) const;
lcLibraryPrimitive* FindPrimitive(const char* Name) const;
bool LoadPrimitive(lcLibraryPrimitive* Primitive);
bool SupportsStudLogo() const;
@ -152,7 +161,6 @@ public:
void UnloadUnusedParts();
std::map<std::string, PieceInfo*> mPieces;
std::map<std::string, lcLibraryPrimitive*> mPrimitives;
int mNumOfficialPieces;
std::vector<lcTexture*> mTextures;
@ -182,7 +190,9 @@ protected:
bool ReadDirectoryCacheFile(const QString& FileName, lcMemFile& CacheFile);
bool WriteDirectoryCacheFile(const QString& FileName, lcMemFile& CacheFile);
bool GetStudLogoFile(lcMemFile& PrimFile, int StudLogo, bool OpenStud);
void UpdateStudLogoSource();
std::vector<std::unique_ptr<lcLibrarySource>> mSources;
QMutex mLoadMutex;
QList<QFuture<void>> mLoadFutures;

View file

@ -96,7 +96,11 @@
<file>resources/parts_cancel.png</file>
<file>resources/archive.png</file>
<file>resources/library.zip</file>
<file>resources/primitives.zip</file>
<file>resources/studlogo1.zip</file>
<file>resources/studlogo2.zip</file>
<file>resources/studlogo3.zip</file>
<file>resources/studlogo4.zip</file>
<file>resources/studlogo5.zip</file>
<file>resources/ldconfig.ldr</file>
<file>resources/minifig.ini</file>
<file>resources/ldraw.xml</file>

Binary file not shown.

BIN
resources/studlogo1.zip Normal file

Binary file not shown.

BIN
resources/studlogo2.zip Normal file

Binary file not shown.

BIN
resources/studlogo3.zip Normal file

Binary file not shown.

BIN
resources/studlogo4.zip Normal file

Binary file not shown.

BIN
resources/studlogo5.zip Normal file

Binary file not shown.