io.cpp

changeset 25
c74bb88f537d
parent 24
d2d4d0154338
equal deleted inserted replaced
24:d2d4d0154338 25:c74bb88f537d
2 2
3 #include "common.h" 3 #include "common.h"
4 #include "io.h" 4 #include "io.h"
5 #include "misc.h" 5 #include "misc.h"
6 #include "bbox.h" 6 #include "bbox.h"
7 #include "gui.h"
7 8
8 vector<str> g_zaFileLoadPaths; 9 vector<str> g_zaFileLoadPaths;
9 10
10 // ============================================================================= 11 // =============================================================================
11 // IO_FindLoadedFile (str) 12 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
12 // 13 // =============================================================================
13 // Returns a pointer to the first found open file with the given name. 14 OpenFile* findLoadedFile (str name) {
14 // =============================================================================
15 OpenFile* IO_FindLoadedFile (str name) {
16 for (ulong i = 0; i < g_LoadedFiles.size(); i++) { 15 for (ulong i = 0; i < g_LoadedFiles.size(); i++) {
17 OpenFile* const file = g_LoadedFiles[i]; 16 OpenFile* const file = g_LoadedFiles[i];
18 if (file->zFileName == name) 17 if (file->zFileName == name)
19 return file; 18 return file;
20 } 19 }
21 20
22 return nullptr; 21 return nullptr;
23 } 22 }
24 23
25 // ============================================================================= 24 // =============================================================================
26 // IO_OpenLDrawFile (str) 25 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
27 // 26 // =============================================================================
28 // Opens the given file and parses the LDraw code within. 27 OpenFile* openDATFile (str path) {
29 // =============================================================================
30 OpenFile* IO_OpenLDrawFile (str path) {
31 logf ("Opening %s...\n", path.chars()); 28 logf ("Opening %s...\n", path.chars());
32 29
33 FILE* fp = fopen (path.chars (), "r"); 30 FILE* fp = fopen (path.chars (), "r");
34 31
35 if (!fp) { 32 if (!fp) {
67 } 64 }
68 65
69 fclose (fp); 66 fclose (fp);
70 67
71 for (ulong i = 0; i < lines.size(); ++i) { 68 for (ulong i = 0; i < lines.size(); ++i) {
72 LDObject* obj = ParseLine (lines[i]); 69 LDObject* obj = parseLine (lines[i]);
73 load->objects.push_back (obj); 70 load->objects.push_back (obj);
74 71
75 // Check for warnings 72 // Check for parse errors and warn abotu tthem
76 if (obj->getType() == OBJ_Gibberish) { 73 if (obj->getType() == OBJ_Gibberish) {
77 logf (LOG_Warning, "Couldn't parse line #%lu: %s\n", 74 logf (LOG_Warning, "Couldn't parse line #%lu: %s\n",
78 i, static_cast<LDGibberish*> (obj)->zReason.chars()); 75 i, static_cast<LDGibberish*> (obj)->zReason.chars());
79 logf (LOG_Warning, "- Line was: %s\n", lines[i].chars()); 76 logf (LOG_Warning, "- Line was: %s\n", lines[i].chars());
80 numWarnings++; 77 numWarnings++;
88 85
89 return load; 86 return load;
90 } 87 }
91 88
92 // ============================================================================= 89 // =============================================================================
93 // isNumber (char*) [static] 90 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
94 // 91 // =============================================================================
95 // Returns whether a given string represents a floating point number 92 // Clear everything from the model
96 // TODO: Does LDraw support scientific notation? 93 void OpenFile::close () {
97 // ============================================================================= 94 for (ulong j = 0; j < objects.size(); ++j)
98 static bool isNumber (char* sToken) { 95 delete objects[j];
99 char* sPointer = &sToken[0]; 96
100 bool bGotDot = false; 97 delete this;
101 98 }
102 // Allow leading hyphen for negatives 99
103 if (*sPointer == '-') 100 // =============================================================================
104 sPointer++; 101 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
105 102 // =============================================================================
106 while (*sPointer != '\0') { 103 void closeAll () {
107 if (*sPointer == '.' && !bGotDot) { 104 if (!g_LoadedFiles.size())
108 // Decimal point 105 return;
109 bGotDot = true; 106
110 sPointer++; 107 // Remove all loaded files and the objects they contain
111 continue; 108 for (ushort i = 0; i < g_LoadedFiles.size(); i++) {
112 } 109 OpenFile* f = g_LoadedFiles[i];
110 f->close ();
111 }
112
113 // Clear the array
114 g_LoadedFiles.clear();
115 g_CurrentFile = NULL;
116
117 g_qWindow->R->hardRefresh();
118 }
119
120 // =============================================================================
121 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
122 // =============================================================================
123 void newFile () {
124 // Create a new anonymous file and set it to our current
125 closeAll ();
126
127 OpenFile* f = new OpenFile;
128 f->zFileName = "";
129 g_LoadedFiles.push_back (f);
130 g_CurrentFile = f;
131
132 g_BBox.calculate();
133 g_qWindow->buildObjList ();
134 g_qWindow->R->hardRefresh();
135 }
136
137 // =============================================================================
138 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
139 // =============================================================================
140 void openMainFile (str zPath) {
141 closeAll ();
142
143 OpenFile* pFile = openDATFile (zPath);
144 g_CurrentFile = pFile;
145
146 // Recalculate the bounding box
147 g_BBox.calculate();
148
149 // Rebuild the object tree view now.
150 g_qWindow->buildObjList ();
151 g_qWindow->setTitle ();
152 }
153
154 // =============================================================================
155 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
156 // =============================================================================
157 void OpenFile::save (str zPath) {
158 if (!~zPath)
159 zPath = zFileName;
160
161 FILE* fp = fopen (zPath, "w");
162 if (!fp)
163 return;
164
165 // Write all entries now
166 for (ulong i = 0; i < objects.size(); ++i) {
167 LDObject* obj = objects[i];
113 168
114 if (*sPointer >= '0' && *sPointer <= '9') { 169 // LDraw requires lines to have DOS line endings
115 sPointer++; 170 str zLine = str::mkfmt ("%s\r\n",obj->getContents ().chars ());
116 continue; // Digit
117 }
118 171
119 // If the above cases didn't catch this character, it was 172 fwrite (zLine.chars(), 1, ~zLine, fp);
120 // illegal and this is therefore not a number. 173 }
121 return false; 174
122 } 175 fclose (fp);
123 176 }
124 return true; 177
125 } 178 // =============================================================================
126 179 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
127 // =============================================================================
128 // ParseLine (str)
129 //
130 // Parses a string line containing an LDraw object and returns the object parsed.
131 // ============================================================================= 180 // =============================================================================
132 #define CHECK_TOKEN_COUNT(N) \ 181 #define CHECK_TOKEN_COUNT(N) \
133 if (tokens.size() != N) \ 182 if (tokens.size() != N) \
134 return new LDGibberish (zLine, "Bad amount of tokens"); 183 return new LDGibberish (zLine, "Bad amount of tokens");
135 184
137 for (ushort i = MIN; i <= MAX; ++i) \ 186 for (ushort i = MIN; i <= MAX; ++i) \
138 if (!isNumber (tokens[i])) \ 187 if (!isNumber (tokens[i])) \
139 return new LDGibberish (zLine, str::mkfmt ("Token #%u was `%s`, expected a number", \ 188 return new LDGibberish (zLine, str::mkfmt ("Token #%u was `%s`, expected a number", \
140 (i + 1), tokens[i].chars())); 189 (i + 1), tokens[i].chars()));
141 190
142 LDObject* ParseLine (str zLine) { 191 LDObject* parseLine (str zLine) {
143 str zNoWhitespace = zLine; 192 str zNoWhitespace = zLine;
144 StripWhitespace (zNoWhitespace); 193 stripWhitespace (zNoWhitespace);
145 if (!~zNoWhitespace) { 194 if (!~zNoWhitespace) {
146 // Line was empty, or only consisted of whitespace 195 // Line was empty, or only consisted of whitespace
147 return new LDEmpty; 196 return new LDEmpty;
148 } 197 }
149 198
175 #ifndef WIN32 224 #ifndef WIN32
176 tokens[14].replace ("\\", "/"); 225 tokens[14].replace ("\\", "/");
177 #endif // WIN32 226 #endif // WIN32
178 227
179 // Try open the file 228 // Try open the file
180 OpenFile* pFile = IO_FindLoadedFile (tokens[14]); 229 OpenFile* pFile = findLoadedFile (tokens[14]);
181 if (!pFile) 230 if (!pFile)
182 pFile = IO_OpenLDrawFile (tokens[14]); 231 pFile = openDATFile (tokens[14]);
183 232
184 // If we cannot open the file, mark it an error 233 // If we cannot open the file, mark it an error
185 if (!pFile) 234 if (!pFile)
186 return new LDGibberish (zLine, "Could not open referred file"); 235 return new LDGibberish (zLine, "Could not open referred file");
187 236
188 LDSubfile* obj = new LDSubfile; 237 LDSubfile* obj = new LDSubfile;
189 obj->dColor = atoi (tokens[1]); 238 obj->dColor = atoi (tokens[1]);
190 obj->vPosition = ParseVertex (zLine, 2); // 2 - 4 239 obj->vPosition = parseVertex (zLine, 2); // 2 - 4
191 240
192 for (short i = 0; i < 9; ++i) 241 for (short i = 0; i < 9; ++i)
193 obj->faMatrix[i] = atof (tokens[i + 5]); // 5 - 13 242 obj->faMatrix[i] = atof (tokens[i + 5]); // 5 - 13
194 243
195 obj->zFileName = tokens[14]; 244 obj->zFileName = tokens[14];
202 CHECK_TOKEN_COUNT (8) 251 CHECK_TOKEN_COUNT (8)
203 CHECK_TOKEN_NUMBERS (1, 7) 252 CHECK_TOKEN_NUMBERS (1, 7)
204 253
205 // Line 254 // Line
206 LDLine* obj = new LDLine; 255 LDLine* obj = new LDLine;
207 obj->dColor = GetWordInt (zLine, 1); 256 obj->dColor = getWordInt (zLine, 1);
208 for (short i = 0; i < 2; ++i) 257 for (short i = 0; i < 2; ++i)
209 obj->vaCoords[i] = ParseVertex (zLine, 2 + (i * 3)); // 2 - 7 258 obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 7
210 return obj; 259 return obj;
211 } 260 }
212 261
213 case 3: 262 case 3:
214 { 263 {
215 CHECK_TOKEN_COUNT (11) 264 CHECK_TOKEN_COUNT (11)
216 CHECK_TOKEN_NUMBERS (1, 10) 265 CHECK_TOKEN_NUMBERS (1, 10)
217 266
218 // Triangle 267 // Triangle
219 LDTriangle* obj = new LDTriangle; 268 LDTriangle* obj = new LDTriangle;
220 obj->dColor = GetWordInt (zLine, 1); 269 obj->dColor = getWordInt (zLine, 1);
221 270
222 for (short i = 0; i < 3; ++i) 271 for (short i = 0; i < 3; ++i)
223 obj->vaCoords[i] = ParseVertex (zLine, 2 + (i * 3)); // 2 - 10 272 obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 10
224 273
225 return obj; 274 return obj;
226 } 275 }
227 276
228 case 4: 277 case 4:
230 CHECK_TOKEN_COUNT (14) 279 CHECK_TOKEN_COUNT (14)
231 CHECK_TOKEN_NUMBERS (1, 13) 280 CHECK_TOKEN_NUMBERS (1, 13)
232 281
233 // Quadrilateral 282 // Quadrilateral
234 LDQuad* obj = new LDQuad; 283 LDQuad* obj = new LDQuad;
235 obj->dColor = GetWordInt (zLine, 1); 284 obj->dColor = getWordInt (zLine, 1);
236 285
237 for (short i = 0; i < 4; ++i) 286 for (short i = 0; i < 4; ++i)
238 obj->vaCoords[i] = ParseVertex (zLine, 2 + (i * 3)); // 2 - 13 287 obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 13
239 288
240 return obj; 289 return obj;
241 } 290 }
242 291
243 case 5: 292 case 5:
245 CHECK_TOKEN_COUNT (14) 294 CHECK_TOKEN_COUNT (14)
246 CHECK_TOKEN_NUMBERS (1, 13) 295 CHECK_TOKEN_NUMBERS (1, 13)
247 296
248 // Conditional line 297 // Conditional line
249 LDCondLine* obj = new LDCondLine; 298 LDCondLine* obj = new LDCondLine;
250 obj->dColor = GetWordInt (zLine, 1); 299 obj->dColor = getWordInt (zLine, 1);
251 300
252 for (short i = 0; i < 2; ++i) 301 for (short i = 0; i < 2; ++i)
253 obj->vaCoords[i] = ParseVertex (zLine, 2 + (i * 3)); // 2 - 7 302 obj->vaCoords[i] = parseVertex (zLine, 2 + (i * 3)); // 2 - 7
254 303
255 for (short i = 0; i < 2; ++i) 304 for (short i = 0; i < 2; ++i)
256 obj->vaControl[i] = ParseVertex (zLine, 8 + (i * 3)); // 8 - 13 305 obj->vaControl[i] = parseVertex (zLine, 8 + (i * 3)); // 8 - 13
257 return obj; 306 return obj;
258 } 307 }
259 308
260 default: // Strange line we couldn't parse 309 default: // Strange line we couldn't parse
261 return new LDGibberish (zLine, "Unknown line code number"); 310 return new LDGibberish (zLine, "Unknown line code number");

mercurial