#pragma once #include "lc_context.h" #include "lc_math.h" #include "lc_meshloader.h" class PieceInfo; class lcZipFile; class lcLibraryMeshData; class lcThumbnailManager; enum class lcStudStyle { Plain, ThinLinesLogo, OutlineLogo, SharpTopLogo, RoundedTopLogo, FlattenedLogo, HighContrast, HighContrastLogo, Count }; constexpr bool lcIsHighContrast(lcStudStyle StudStyle) { return StudStyle == lcStudStyle::HighContrast || StudStyle == lcStudStyle::HighContrastLogo; } enum class lcZipFileType { Official, Unofficial, StudStyle, Count }; enum class lcLibraryFolderType { Official, Unofficial, Count }; enum class lcPrimitiveState { NotLoaded, Loading, Loaded }; class lcLibraryPrimitive { public: explicit lcLibraryPrimitive(QString&& FileName, const char* Name, lcZipFileType ZipFileType, quint32 ZipFileIndex, bool Stud, bool StudStyle, bool SubFile) : mFileName(std::move(FileName)) { strncpy(mName, Name, sizeof(mName)-1); mName[sizeof(mName) - 1] = 0; mZipFileType = ZipFileType; mZipFileIndex = ZipFileIndex; mState = lcPrimitiveState::NotLoaded; mStud = Stud; mStudStyle = StudStyle; mSubFile = SubFile; } void SetZipFile(lcZipFileType ZipFileType, quint32 ZipFileIndex) { mZipFileType = ZipFileType; mZipFileIndex = ZipFileIndex; } void Unload() { mState = lcPrimitiveState::NotLoaded; mMeshData.Clear(); } QString mFileName; char mName[LC_MAXNAME]; lcZipFileType mZipFileType; quint32 mZipFileIndex; lcPrimitiveState mState; bool mStud; bool mStudStyle; bool mSubFile; lcLibraryMeshData mMeshData; }; enum class lcLibrarySourceType { Library, StudStyle }; struct lcLibrarySource { lcLibrarySource() = default; ~lcLibrarySource() { for (const auto& PrimitiveIt : Primitives) delete PrimitiveIt.second; } lcLibrarySource(const lcLibrarySource&) = delete; lcLibrarySource(lcLibrarySource&&) = delete; lcLibrarySource& operator=(const lcLibrarySource&) = delete; lcLibrarySource& operator=(lcLibrarySource&&) = delete; lcLibrarySourceType Type; std::map Primitives; }; class lcPiecesLibrary : public QObject { Q_OBJECT public: lcPiecesLibrary(); ~lcPiecesLibrary(); lcPiecesLibrary(const lcPiecesLibrary&) = delete; lcPiecesLibrary(lcPiecesLibrary&&) = delete; lcPiecesLibrary& operator=(const lcPiecesLibrary&) = delete; lcPiecesLibrary& operator=(lcPiecesLibrary&&) = delete; lcThumbnailManager* GetThumbnailManager() const { return mThumbnailManager.get(); } bool Load(const QString& LibraryPath, bool ShowProgress); void LoadColors(); void Unload(); void RemoveTemporaryPieces(); void RemovePiece(PieceInfo* Info); void RenamePiece(PieceInfo* Info, const char* NewName); PieceInfo* FindPiece(const char* PieceName, Project* Project, bool CreatePlaceholder, bool SearchProjectFolder); void LoadPieceInfo(PieceInfo* Info, bool Wait, bool Priority); void ReleasePieceInfo(PieceInfo* Info); bool LoadBuiltinPieces(); bool LoadPieceData(PieceInfo* Info); void LoadQueuedPiece(); void WaitForLoadQueue(); lcTexture* FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder); bool LoadTexture(lcTexture* Texture); void ReleaseTexture(lcTexture* Texture); bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const; void GetCategoryEntries(int CategoryIndex, bool GroupPieces, std::vector& SinglePieces, std::vector& GroupedPieces); void GetCategoryEntries(const char* CategoryKeywords, bool GroupPieces, std::vector& SinglePieces, std::vector& GroupedPieces); void GetParts(std::vector& Parts) const; std::vector GetPartsFromSet(const std::vector& PartIds) const; std::string GetPartId(const PieceInfo* Info) const; void GetPrimitiveFile(lcLibraryPrimitive* Primitive, std::function Callback); void GetPieceFile(const char* FileName, std::function Callback); bool IsPrimitive(const char* Name) const; lcLibraryPrimitive* FindPrimitive(const char* Name) const; bool LoadPrimitive(lcLibraryPrimitive* Primitive); bool SupportsStudStyle() const; void SetStudStyle(lcStudStyle StudStyle, bool Reload, bool StudCylinderColorEnabled); lcStudStyle GetStudStyle() const { return mStudStyle; } void SetOfficialPieces() { if (mZipFiles[static_cast(lcZipFileType::Official)]) mNumOfficialPieces = (int)mPieces.size(); } bool ShouldCancelLoading() const { return mCancelLoading; } void UpdateBuffers(lcContext* Context); void UnloadUnusedParts(); std::map mPieces; int mNumOfficialPieces; std::vector mTextures; QDir mLibraryDir; bool mBuffersDirty; lcVertexBuffer mVertexBuffer; lcIndexBuffer mIndexBuffer; signals: void PartLoaded(PieceInfo* Info); void ColorsLoaded(); protected: bool OpenArchive(const QString& FileName, lcZipFileType ZipFileType); bool OpenArchive(std::unique_ptr File, lcZipFileType ZipFileType); bool OpenDirectory(const QDir& LibraryDir, bool ShowProgress); void ReadArchiveDescriptions(const QString& OfficialFileName, const QString& UnofficialFileName); void ReadDirectoryDescriptions(const QFileInfoList (&FileLists)[static_cast(lcLibraryFolderType::Count)], bool ShowProgress); bool ReadArchiveCacheFile(const QString& FileName, lcMemFile& CacheFile); bool WriteArchiveCacheFile(const QString& FileName, lcMemFile& CacheFile); bool LoadCacheIndex(const QString& FileName); bool SaveArchiveCacheIndex(const QString& FileName); bool LoadCachePiece(PieceInfo* Info); bool SaveCachePiece(PieceInfo* Info); bool ReadDirectoryCacheFile(const QString& FileName, lcMemFile& CacheFile); bool WriteDirectoryCacheFile(const QString& FileName, lcMemFile& CacheFile); static bool IsStudPrimitive(const char* FileName); static bool IsStudStylePrimitive(const char* FileName); void UpdateStudStyleSource(); void ReleaseBuffers(); std::vector> mSources; #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) QRecursiveMutex mLoadMutex; #else QMutex mLoadMutex; #endif QList> mLoadFutures; QList mLoadQueue; QMutex mTextureMutex; lcStudStyle mStudStyle; bool mStudCylinderColorEnabled; std::unique_ptr mThumbnailManager; QString mCachePath; qint64 mArchiveCheckSum[4]; std::unique_ptr mZipFiles[static_cast(lcZipFileType::Count)]; bool mHasUnofficial; bool mCancelLoading; };