1 #ifndef __LDLMODEL_H__
2 #define __LDLMODEL_H__
3 
4 #include <TCFoundation/TCAlertSender.h>
5 #include <LDLoader/LDLFileLine.h>
6 #include <LDLoader/LDLError.h>
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <fstream>
10 
11 class TCDictionary;
12 class LDLMainModel;
13 class LDLCommentLine;
14 class LDLModelLine;
15 class TCImage;
16 
17 typedef enum
18 {
19 	// WARNING: Increasing this list past 4 members requires more bits in flags.
20 	// Note that even now, it requires 3 bits, because the compiler treats it
21 	// as a signed integer.  When the value 2 is sign-extended, it becomes -2,
22 	// which doesn't match.
23 	BFCUnknownState,
24 	BFCOffState,
25 	BFCOnState,
26 	BFCForcedOnState
27 } BFCState;
28 
29 typedef bool (*LDLFileCaseCallback)(char *filename);
30 typedef void (TCObject::*LDLScanPointCallback)(const TCVector &point,
31 	const LDLFileLine *pFileLine);
32 struct LDrawIniS;
33 
34 class LDLModel : public TCAlertSender
35 {
36 public:
37 	LDLModel(void);
38 	LDLModel(const LDLModel &other);
39 	virtual TCObject *copy(void) const;
40 	// Color numbers might become dynamic, so not static.
41 	virtual void getRGBA(int colorNumber, int& r, int& g, int& b, int& a);
42 	virtual TCULong getPackedRGBA(int colorNumber);
43 	virtual int getEdgeColorNumber(int colorNumber);
44 	virtual bool hasSpecular(int colorNumber);
45 	virtual bool hasShininess(int colorNumber);
46 	virtual void getSpecular(int colorNumber, float *specular);
47 	virtual void getShininess(int colorNumber, float &shininess);
48 	virtual LDLModel *subModelNamed(const char *subModelName,
49 		bool lowRes = false, bool secondAttempt = false,
50 		const LDLModelLine *fileLine = NULL, bool knownPart = false);
getFilename(void)51 	virtual const char *getFilename(void) const { return m_filename; }
52 	virtual void setFilename(const char *filename);
getName(void)53 	virtual const char *getName(void) const { return m_name; }
getDescription(void)54 	virtual const char *getDescription(void) const { return m_description; }
getAuthor(void)55 	virtual const char *getAuthor(void) const { return m_author; }
56 	virtual void setName(const char *name);
57 	bool load(std::ifstream &stream, bool trackProgress = true);
58 	void print(int indent) const;
59 	virtual bool parse(void);
60 	virtual TCDictionary* getLoadedModels(void);
61 	virtual bool getLowResStuds(void) const;
62 	virtual LDLError *newError(LDLErrorType type, const LDLFileLine &fileLine,
63 		CUCSTR format, va_list argPtr);
64 	virtual LDLError *newError(LDLErrorType type, const LDLFileLine &fileLine,
65 		CUCSTR format, ...);
66 	virtual LDLError *newError(LDLErrorType type, CUCSTR format,
67 		va_list argPtr);
68 	virtual LDLError *newError(LDLErrorType type, CUCSTR format, ...);
69 	virtual LDLFileLineArray *getFileLines(bool initialize = false);
getFileLines(void)70 	virtual const LDLFileLineArray *getFileLines(void) const
71 	{
72 		return m_fileLines;
73 	}
getStepIndices(void)74 	virtual const IntList &getStepIndices(void) const { return m_stepIndices; }
getActiveLineCount(void)75 	virtual int getActiveLineCount(void) const { return m_activeLineCount; }
setActiveLineCount(int value)76 	virtual void setActiveLineCount(int value) { m_activeLineCount = value; }
77 	virtual bool colorNumberIsTransparent(int colorNumber);
isMainModel(void)78 	virtual bool isMainModel(void) const { return false; }
79 	virtual void scanPoints(TCObject *scanner,
80 		LDLScanPointCallback scanPointCallback, const TCFloat *matrix,
81 		int step = -1, bool watchBBoxIgnore = false) const;
82 	virtual void getBoundingBox(TCVector &min, TCVector &max) const;
83 	virtual TCFloat getMaxRadius(const TCVector &center, bool watchBBoxIgnore);
84 
85 	// Flags
86 	// Note that bit flags can cause odd results; thus returning the != false,
87 	// instead of returning the flag value directly.
isPart(void)88 	bool isPart(void) const { return m_flags.part != false; }
isPrimitive(void)89 	bool isPrimitive(void) const { return m_flags.primitive != false; }
isSubPart(void)90 	bool isSubPart(void) const { return m_flags.subPart != false; }
isMPD(void)91 	bool isMPD(void) const { return m_flags.mpd != false; }
getNoShrinkFlag(void)92 	bool getNoShrinkFlag(void) const { return m_flags.noShrink != false; }
setNoShrinkFlag(bool value)93 	void setNoShrinkFlag(bool value) { m_flags.noShrink = value; }
isOfficial(void)94 	bool isOfficial(void) const { return m_flags.official != false; }
isUnOfficial(void)95 	bool isUnOfficial(void) const { return m_flags.unofficial != false; }
hasStuds(void)96 	bool hasStuds(void) const { return m_flags.hasStuds != false; }
97 	bool hasBoundingBox(void) const;
98 	void copyPublicFlags(const LDLModel *src);
99 	void copyBoundingBox(const LDLModel *src);
100 	bool searchNext(const std::string &searchString, IntVector& path,
101 		int loopEnd, TCULong activeLineTypes) const;
102 	bool searchPrevious(const std::string &searchString, IntVector& path,
103 		int loopEnd, TCULong activeLineTypes) const;
104 	//bool hasBoundingBox(void) const { return m_flags.haveBoundingBox != false; }
105 
106 
getBFCState(void)107 	BFCState getBFCState(void) { return m_flags.bfcCertify; }
108 
getBFCOn(void)109 	bool getBFCOn(void)
110 	{
111 		return m_flags.bfcCertify == BFCOnState ||
112 			m_flags.bfcCertify == BFCForcedOnState;
113 	}
114 
115 	virtual void cancelLoad(void);
116 	virtual bool getLoadCanceled(void);
getMainModel(void)117 	LDLMainModel *getMainModel(void) { return m_mainModel; }
setMainModel(LDLMainModel * value)118 	void setMainModel(LDLMainModel *value) { m_mainModel = value; }
getMainModel(void)119 	const LDLMainModel *getMainModel(void) const { return m_mainModel; }
120 	virtual TCObject *getAlertSender(void);
121 	virtual int loadMpdTexmaps(void);
122 
123 	static const char *lDrawDir(bool defaultValue = false);
124 	static void setLDrawDir(const char *value);
125 	static void setFileCaseCallback(LDLFileCaseCallback value);
getFileCaseCallback(void)126 	static LDLFileCaseCallback getFileCaseCallback(void)
127 	{
128 		return fileCaseCallback;
129 	}
130 	static bool openFile(const char *filename, std::ifstream &modelStream);
131 	static bool openStream(const char *filename, std::ifstream &stream);
132 	static void combinePathParts(std::string &path, const std::string &left,
133 		const std::string& middle, const std::string &right = std::string());
134 protected:
135 	virtual void dealloc(void);
136 	bool openTexmap(const char *filename, std::ifstream &texmapStream,
137 		std::string &path);
138 	virtual bool openSubModelNamed(const char* subModelName,
139 		std::string &subModelPath, std::ifstream &fileStream, bool knownPart,
140 		bool *pLoop = NULL, bool isText = true);
141 	virtual bool initializeNewSubModel(LDLModel* subModel,
142 		const char *dictName, std::ifstream &subModelStream);
143 	virtual bool initializeNewSubModel(LDLModel* subModel,
144 		const char *dictName);
145 	virtual bool read(std::ifstream &stream);
146 	virtual int parseComment(int index, LDLCommentLine *commentLine);
147 	virtual int parseMPDMeta(int index, const char *filename);
148 	virtual int parseBFCMeta(LDLCommentLine *commentLine);
149 	virtual int parseTexmapMeta(LDLCommentLine *commentLine);
150 	virtual int parseBBoxIgnoreMeta(LDLCommentLine *commentLine);
151 	virtual void readComment(LDLCommentLine *commentLine);
152 	virtual void sendAlert(LDLError *alert);
153 	virtual void sendAlert(LDLErrorType type, LDLAlertLevel level,
154 		CUCSTR format, va_list argPtr);
155 	virtual void sendAlert(LDLErrorType type, LDLAlertLevel level,
156 		const LDLFileLine &fileLine, CUCSTR format, va_list argPtr);
157 	virtual void reportError(LDLErrorType type, const LDLFileLine &fileLine,
158 		CUCSTR format, ...);
159 	virtual void reportWarning(LDLErrorType type, const LDLFileLine &fileLine,
160 		CUCSTR format, ...);
161 	virtual void reportError(LDLErrorType type, CUCSTR format, ...);
162 	virtual void reportWarning(LDLErrorType type, CUCSTR format, ...);
163 	virtual void reportProgress(const char *message, float progress,
164 		bool mainOnly = true);
165 	virtual void reportProgress(const wchar_t *message, float progress,
166 		bool mainOnly = true);
167 	virtual bool isSubPart(const char *subModelName);
168 	virtual bool isAbsolutePath(const char *path);
169 //	virtual void processModelLine(LDLModelLine *modelLine);
170 	virtual bool openModelFile(const char *filename, std::ifstream &modelStream,
171 		bool isText, bool knownPart = false);
172 	virtual void calcBoundingBox(void) const;
173 	virtual void calcMaxRadius(const TCVector &center, bool watchBBoxIgnore);
174 	void scanBoundingBoxPoint(const TCVector &point, LDLFileLine *pFileLine);
175 	void scanRadiusSquaredPoint(const TCVector &point, LDLFileLine *pFileLine);
176 	void sendUnofficialWarningIfPart(const LDLModel *subModel,
177 		const LDLModelLine *fileLine, const char *subModelName);
178 	void endTexmap(void);
179 	void extractData();
180 
181 	static bool verifyLDrawDir(const char *value);
182 	static void initCheckDirs();
183 
184 	char *m_filename;
185 	char *m_name;
186 	char *m_author;
187 	char *m_description;
188 	LDLFileLineArray *m_fileLines;
189 	LDLModelArray *m_mpdTexmapModels;
190 	LDLCommentLineArray *m_mpdTexmapLines;
191 	TCImageArray *m_mpdTexmapImages;
192 	LDLMainModel *m_mainModel;
193 	IntList m_stepIndices;
194 	int m_activeLineCount;
195 	LDLModel *m_activeMPDModel;
196 
197 	TCVector m_boundingMin;
198 	TCVector m_boundingMax;
199 	TCVector m_center;
200 	TCFloat m_maxRadius;
201 	TCFloat m_maxFullRadius;
202 	std::string m_texmapFilename;
203 	TCImage *m_texmapImage;
204 	LDLFileLine::TexmapType m_texmapType;
205 	TCVector m_texmapPoints[3];
206 	TCFloat m_texmapExtra[2];
207 	std::vector<TCByte> m_data;
208 	LDLCommentLine *m_dataLine;
209 	struct
210 	{
211 		// Private flags
212 		bool loadingPart:1;			// Temporal
213 		bool loadingSubPart:1;		// Temporal
214 		bool loadingPrimitive:1;	// Temporal
215 		bool loadingUnoffic:1;		// Temporal
216 		bool mainModelLoaded:1;		// Temporal
217 		bool mainModelParsed:1;		// Temporal
218 		bool started:1;				// Temporal
219 		bool bfcClip:1;				// Temporal
220 		bool bfcWindingCCW:1;		// Temporal
221 		bool bfcInvertNext:1;		// Temporal
222 		bool haveBoundingBox:1;		// Temporal
223 		bool haveMaxRadius:1;		// Temporal
224 		bool haveMaxFullRadius:1;	// Temporal
225 		bool fullRadius:1;			// Temporal
226 		bool texmapStarted:1;		// Temporal
227 		bool texmapFallback:1;		// Temporal
228 		bool texmapNext:1;			// Temporal
229 		bool texmapValid:1;			// Temporal
230 		// Public flags
231 		bool part:1;
232 		bool subPart:1;
233 		bool primitive:1;
234 		bool mpd:1;
235 		bool noShrink:1;
236 		bool official:1;
237 		bool unofficial:1;
238 		bool hasStuds:1;
239 		BFCState bfcCertify:3;
240 		bool bboxIgnoreOn:1;
241 		bool bboxIgnoreBegun:1;
242 	} m_flags;
243 
244 	static StringList sm_checkDirs;
245 	static char *sm_systemLDrawDir;
246 	static char *sm_defaultLDrawDir;
247 	static LDrawIniS *sm_lDrawIni;
248 	static int sm_modelCount;
249 	static LDLFileCaseCallback fileCaseCallback;
250 	static class LDLModelCleanup
251 	{
252 	public:
253 		~LDLModelCleanup(void);
254 	} sm_cleanup;
255 	friend class LDLModelCleanup;
256 };
257 
258 #endif // __LDLMODEL_H__
259