1 #pragma once
2 
3 #include "lc_context.h"
4 #include "lc_mesh.h"
5 #include "lc_math.h"
6 #include "lc_array.h"
7 #include "lc_meshloader.h"
8 
9 class PieceInfo;
10 class lcZipFile;
11 class lcLibraryMeshData;
12 
13 enum class lcStudStyle
14 {
15 	Plain,
16 	ThinLinesLogo,
17 	OutlineLogo,
18 	SharpTopLogo,
19 	RoundedTopLogo,
20 	FlattenedLogo,
21 	HighContrast,
22 	HighContrastLogo,
23 	Count
24 };
25 
lcIsHighContrast(lcStudStyle StudStyle)26 inline bool lcIsHighContrast(lcStudStyle StudStyle)
27 {
28 	return StudStyle == lcStudStyle::HighContrast || StudStyle == lcStudStyle::HighContrastLogo;
29 }
30 
31 enum class lcZipFileType
32 {
33 	Official,
34 	Unofficial,
35 	StudStyle,
36 	Count
37 };
38 
39 enum class lcLibraryFolderType
40 {
41 	Official,
42 	Unofficial,
43 	Count
44 };
45 
46 enum class lcPrimitiveState
47 {
48 	NotLoaded,
49 	Loading,
50 	Loaded
51 };
52 
53 class lcLibraryPrimitive
54 {
55 public:
lcLibraryPrimitive(QString && FileName,const char * Name,lcZipFileType ZipFileType,quint32 ZipFileIndex,bool Stud,bool StudStyle,bool SubFile)56 	explicit lcLibraryPrimitive(QString&& FileName, const char* Name, lcZipFileType ZipFileType, quint32 ZipFileIndex, bool Stud, bool StudStyle, bool SubFile)
57 		: mFileName(std::move(FileName))
58 	{
59 		strncpy(mName, Name, sizeof(mName)-1);
60 		mName[sizeof(mName) - 1] = 0;
61 
62 		mZipFileType = ZipFileType;
63 		mZipFileIndex = ZipFileIndex;
64 		mState = lcPrimitiveState::NotLoaded;
65 		mStud = Stud;
66 		mStudStyle = StudStyle;
67 		mSubFile = SubFile;
68 	}
69 
SetZipFile(lcZipFileType ZipFileType,quint32 ZipFileIndex)70 	void SetZipFile(lcZipFileType ZipFileType, quint32 ZipFileIndex)
71 	{
72 		mZipFileType = ZipFileType;
73 		mZipFileIndex = ZipFileIndex;
74 	}
75 
Unload()76 	void Unload()
77 	{
78 		mState = lcPrimitiveState::NotLoaded;
79 		mMeshData.Clear();
80 	}
81 
82 	QString mFileName;
83 	char mName[LC_MAXNAME];
84 	lcZipFileType mZipFileType;
85 	quint32 mZipFileIndex;
86 	lcPrimitiveState mState;
87 	bool mStud;
88 	bool mStudStyle;
89 	bool mSubFile;
90 	lcLibraryMeshData mMeshData;
91 };
92 
93 enum class lcLibrarySourceType
94 {
95 	Library,
96 	StudStyle
97 };
98 
99 struct lcLibrarySource
100 {
~lcLibrarySourcelcLibrarySource101 	~lcLibrarySource()
102 	{
103 		for (const auto& PrimitiveIt : Primitives)
104 			delete PrimitiveIt.second;
105 	}
106 
107 	lcLibrarySourceType Type;
108 	std::map<std::string, lcLibraryPrimitive*> Primitives;
109 };
110 
111 class lcPiecesLibrary : public QObject
112 {
113 	Q_OBJECT
114 
115 public:
116 	lcPiecesLibrary();
117 	~lcPiecesLibrary();
118 
119 	lcPiecesLibrary(const lcPiecesLibrary&) = delete;
120 	lcPiecesLibrary& operator=(const lcPiecesLibrary&) = delete;
121 
122 	bool Load(const QString& LibraryPath, bool ShowProgress);
123 	void LoadColors();
124 	void Unload();
125 	void RemoveTemporaryPieces();
126 	void RemovePiece(PieceInfo* Info);
127 
128 	void RenamePiece(PieceInfo* Info, const char* NewName);
129 	PieceInfo* FindPiece(const char* PieceName, Project* Project, bool CreatePlaceholder, bool SearchProjectFolder);
130 	void LoadPieceInfo(PieceInfo* Info, bool Wait, bool Priority);
131 	void ReleasePieceInfo(PieceInfo* Info);
132 	bool LoadBuiltinPieces();
133 	bool LoadPieceData(PieceInfo* Info);
134 	void LoadQueuedPiece();
135 	void WaitForLoadQueue();
136 
137 	lcTexture* FindTexture(const char* TextureName, Project* CurrentProject, bool SearchProjectFolder);
138 	bool LoadTexture(lcTexture* Texture);
139 	void ReleaseTexture(lcTexture* Texture);
140 
141 	bool PieceInCategory(PieceInfo* Info, const char* CategoryKeywords) const;
142 	void GetCategoryEntries(int CategoryIndex, bool GroupPieces, lcArray<PieceInfo*>& SinglePieces, lcArray<PieceInfo*>& GroupedPieces);
143 	void GetCategoryEntries(const char* CategoryKeywords, bool GroupPieces, lcArray<PieceInfo*>& SinglePieces, lcArray<PieceInfo*>& GroupedPieces);
144 	void GetPatternedPieces(PieceInfo* Parent, lcArray<PieceInfo*>& Pieces) const;
145 	void GetParts(lcArray<PieceInfo*>& Parts) const;
146 
147 	std::vector<PieceInfo*> GetPartsFromSet(const std::vector<std::string>& PartIds) const;
148 	std::string GetPartId(const PieceInfo* Info) const;
149 
150 	void GetPrimitiveFile(lcLibraryPrimitive* Primitive, std::function<void(lcFile& File)> Callback);
151 	void GetPieceFile(const char* FileName, std::function<void(lcFile& File)> Callback);
152 
153 	bool IsPrimitive(const char* Name) const;
154 	lcLibraryPrimitive* FindPrimitive(const char* Name) const;
155 	bool LoadPrimitive(lcLibraryPrimitive* Primitive);
156 
157 	bool SupportsStudStyle() const;
158 	void SetStudStyle(lcStudStyle StudStyle, bool Reload);
159 
GetStudStyle()160 	lcStudStyle GetStudStyle() const
161 	{
162 		return mStudStyle;
163 	}
164 
SetOfficialPieces()165 	void SetOfficialPieces()
166 	{
167 		if (mZipFiles[static_cast<int>(lcZipFileType::Official)])
168 			mNumOfficialPieces = (int)mPieces.size();
169 	}
170 
ShouldCancelLoading()171 	bool ShouldCancelLoading() const
172 	{
173 		return mCancelLoading;
174 	}
175 
176 	void UpdateBuffers(lcContext* Context);
177 	void UnloadUnusedParts();
178 
179 	std::map<std::string, PieceInfo*> mPieces;
180 	int mNumOfficialPieces;
181 
182 	std::vector<lcTexture*> mTextures;
183 
184 	QDir mLibraryDir;
185 
186 	bool mBuffersDirty;
187 	lcVertexBuffer mVertexBuffer;
188 	lcIndexBuffer mIndexBuffer;
189 
190 signals:
191 	void PartLoaded(PieceInfo* Info);
192 	void ColorsLoaded();
193 
194 protected:
195 	bool OpenArchive(const QString& FileName, lcZipFileType ZipFileType);
196 	bool OpenArchive(std::unique_ptr<lcFile> File, lcZipFileType ZipFileType);
197 	bool OpenDirectory(const QDir& LibraryDir, bool ShowProgress);
198 	void ReadArchiveDescriptions(const QString& OfficialFileName, const QString& UnofficialFileName);
199 	void ReadDirectoryDescriptions(const QFileInfoList (&FileLists)[static_cast<int>(lcLibraryFolderType::Count)], bool ShowProgress);
200 
201 	bool ReadArchiveCacheFile(const QString& FileName, lcMemFile& CacheFile);
202 	bool WriteArchiveCacheFile(const QString& FileName, lcMemFile& CacheFile);
203 	bool LoadCacheIndex(const QString& FileName);
204 	bool SaveArchiveCacheIndex(const QString& FileName);
205 	bool LoadCachePiece(PieceInfo* Info);
206 	bool SaveCachePiece(PieceInfo* Info);
207 	bool ReadDirectoryCacheFile(const QString& FileName, lcMemFile& CacheFile);
208 	bool WriteDirectoryCacheFile(const QString& FileName, lcMemFile& CacheFile);
209 
210 	static bool IsStudPrimitive(const char* FileName);
211 	static bool IsStudStylePrimitive(const char* FileName);
212 	void UpdateStudStyleSource();
213 
214 	void ReleaseBuffers();
215 
216 	std::vector<std::unique_ptr<lcLibrarySource>> mSources;
217 
218 	QMutex mLoadMutex;
219 	QList<QFuture<void>> mLoadFutures;
220 	QList<PieceInfo*> mLoadQueue;
221 
222 	QMutex mTextureMutex;
223 
224 	lcStudStyle mStudStyle;
225 
226 	QString mCachePath;
227 	qint64 mArchiveCheckSum[4];
228 	std::unique_ptr<lcZipFile> mZipFiles[static_cast<int>(lcZipFileType::Count)];
229 	bool mHasUnofficial;
230 	bool mCancelLoading;
231 };
232