src/primitives.cpp

changeset 358
7885fa5b09c5
parent 321
48e429bfd58c
child 363
75583c9f289d
equal deleted inserted replaced
357:9c954c222996 358:7885fa5b09c5
1 /* 1 /*
2 * LDForge: LDraw parts authoring CAD 2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013 Santeri Piippo 3 * Copyright (C) 2013 Santeri Piippo
4 * 4 *
5 * This program is free software: you can redistribute it and/or modify 5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or 7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version. 8 * (at your option) any later version.
9 * 9 *
10 * This program is distributed in the hope that it will be useful, 10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details. 13 * GNU General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU General Public License 15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */ 17 */
18 18
19 #include <QDir> 19 #include <QDir>
31 static bool g_primListerMutex = false; 31 static bool g_primListerMutex = false;
32 vector<Primitive> g_primitives; 32 vector<Primitive> g_primitives;
33 33
34 static const str g_Other = QObject::tr( "Other" ); 34 static const str g_Other = QObject::tr( "Other" );
35 35
36 static void populateCategories (); 36 static void populateCategories();
37 static void loadPrimitiveCatgories (); 37 static void loadPrimitiveCatgories();
38 38
39 // ============================================================================= 39 // =============================================================================
40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 40 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
41 // ============================================================================= 41 // =============================================================================
42 void loadPrimitives () { 42 void loadPrimitives()
43 print ("Loading primitives...\n"); 43 {
44 44 print( "Loading primitives...\n" );
45 loadPrimitiveCatgories (); 45
46 loadPrimitiveCatgories();
46 47
47 // Try to load prims.cfg 48 // Try to load prims.cfg
48 File conf (config::dirpath () + "prims.cfg", File::Read); 49 File conf( config::dirpath() + "prims.cfg", File::Read );
49 if (!conf) { 50
51 if( !conf )
52 {
50 // No prims.cfg, build it 53 // No prims.cfg, build it
51 PrimitiveLister::start (); 54 PrimitiveLister::start();
52 } else { 55 }
53 for (str line : conf) { 56 else
54 int space = line.indexOf (" "); 57 {
55 if (space == -1) 58 for( str line : conf )
59 {
60 int space = line.indexOf( " " );
61
62 if( space == -1 )
56 continue; 63 continue;
57 64
58 Primitive info; 65 Primitive info;
59 info.name = line.left (space); 66 info.name = line.left( space );
60 info.title = line.mid (space + 1); 67 info.title = line.mid( space + 1 );
61 g_primitives << info; 68 g_primitives << info;
62 } 69 }
63 70
64 populateCategories (); 71 populateCategories();
65 } 72 }
66 } 73 }
67 74
68 // ============================================================================= 75 // =============================================================================
69 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 76 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
70 // ============================================================================= 77 // =============================================================================
71 void recursiveGetFilenames (QDir dir, vector<str>& fnames) { 78 void recursiveGetFilenames( QDir dir, vector<str>& fnames )
72 QFileInfoList flist = dir.entryInfoList (); 79 {
73 for (const QFileInfo& info : flist) { 80 QFileInfoList flist = dir.entryInfoList();
74 if (info.fileName () == "." || info.fileName () == "..") 81
82 for( const QFileInfo & info : flist )
83 {
84 if( info.fileName() == "." || info.fileName() == ".." )
75 continue; // skip . and .. 85 continue; // skip . and ..
76 86
77 if (info.isDir ()) 87 if( info.isDir() )
78 recursiveGetFilenames (QDir (info.absoluteFilePath ()), fnames); 88 recursiveGetFilenames( QDir( info.absoluteFilePath() ), fnames );
79 else 89 else
80 fnames << info.absoluteFilePath (); 90 fnames << info.absoluteFilePath();
81 } 91 }
82 } 92 }
83 93
84 // ============================================================================= 94 // =============================================================================
85 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 95 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
86 // ============================================================================= 96 // =============================================================================
87 void PrimitiveLister::work () { 97 void PrimitiveLister::work()
98 {
88 g_activePrimLister = this; 99 g_activePrimLister = this;
89 m_prims.clear (); 100 m_prims.clear();
90 101
91 QDir dir (LDPaths::prims ()); 102 QDir dir( LDPaths::prims() );
92 assert (dir.exists ()); 103 ulong baselen = dir.absolutePath().length();
93 104 ulong i = 0;
94 ulong baselen = dir.absolutePath ().length ();
95
96 vector<str> fnames; 105 vector<str> fnames;
97 recursiveGetFilenames (dir, fnames); 106
98 emit starting (fnames.size ()); 107 assert( dir.exists() );
99 108 recursiveGetFilenames( dir, fnames );
100 ulong i = 0; 109 emit starting( fnames.size() );
101 for (str fname : fnames) { 110
102 File f (fname, File::Read); 111 for( str fname : fnames )
112 {
113 File f( fname, File::Read );
103 114
104 Primitive info; 115 Primitive info;
105 info.name = fname.mid (baselen + 1); // make full path relative 116 info.name = fname.mid( baselen + 1 ); // make full path relative
106 info.name.replace ('/', '\\'); // use DOS backslashes, they're expected 117 info.name.replace( '/', '\\' ); // use DOS backslashes, they're expected
107 118 info.cat = null;
108 if (!f.readLine (info.title)) 119
120 if( !f.readLine( info.title ))
109 info.title = ""; 121 info.title = "";
110 122
111 info.title = info.title.simplified (); 123 info.title = info.title.simplified();
112 info.cat = null; 124
113 125 if( info.title[0] == '0' )
114 if (info.title[0] == '0') { 126 {
115 info.title.remove (0, 1); // remove 0 127 info.title.remove( 0, 1 ); // remove 0
116 info.title = info.title.simplified (); 128 info.title = info.title.simplified();
117 } 129 }
118 130
119 m_prims << info; 131 m_prims << info;
120 emit update (++i); 132 emit update( ++i );
121 } 133 }
122 134
123 // Save to a config file 135 // Save to a config file
124 File conf (config::dirpath () + "prims.cfg", File::Write); 136 File conf( config::dirpath() + "prims.cfg", File::Write );
125 for (Primitive& info : m_prims) 137
126 fprint (conf, "%1 %2\n", info.name, info.title); 138 for( Primitive & info : m_prims )
127 139 fprint( conf, "%1 %2\n", info.name, info.title );
128 conf.close (); 140
141 conf.close();
129 142
130 g_primListerMutex = true; 143 g_primListerMutex = true;
131 g_primitives = m_prims; 144 g_primitives = m_prims;
132 populateCategories (); 145 populateCategories();
133 g_primListerMutex = false; 146 g_primListerMutex = false;
134 g_activePrimLister = null; 147 g_activePrimLister = null;
135 emit workDone (); 148 emit workDone();
136 } 149 }
137 150
138 // ============================================================================= 151 // =============================================================================
139 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 152 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
140 // ============================================================================= 153 // =============================================================================
141 void PrimitiveLister::start () { 154 void PrimitiveLister::start()
142 if (g_activePrimLister) 155 {
156 if( g_activePrimLister )
143 return; 157 return;
144 158
145 PrimitiveLister* lister = new PrimitiveLister; 159 PrimitiveLister* lister = new PrimitiveLister;
146 QThread* listerThread = new QThread; 160 QThread* listerThread = new QThread;
147 lister->moveToThread (listerThread); 161 lister->moveToThread( listerThread );
148 connect (lister, SIGNAL (starting (ulong)), g_win, SLOT (primitiveLoaderStart (ulong))); 162 connect( lister, SIGNAL( starting( ulong )), g_win, SLOT( primitiveLoaderStart( ulong )) );
149 connect (lister, SIGNAL (update (ulong)), g_win, SLOT (primitiveLoaderUpdate (ulong))); 163 connect( lister, SIGNAL( update( ulong )), g_win, SLOT( primitiveLoaderUpdate( ulong )) );
150 connect (lister, SIGNAL (workDone ()), g_win, SLOT (primitiveLoaderEnd ())); 164 connect( lister, SIGNAL( workDone() ), g_win, SLOT( primitiveLoaderEnd() ));
151 connect (listerThread, SIGNAL (started ()), lister, SLOT (work ())); 165 connect( listerThread, SIGNAL( started() ), lister, SLOT( work() ));
152 connect (listerThread, SIGNAL (finished ()), lister, SLOT (deleteLater ())); 166 connect( listerThread, SIGNAL( finished() ), lister, SLOT( deleteLater() ));
153 listerThread->start (); 167 listerThread->start();
154 } 168 }
155 169
156 static PrimitiveCategory* findCategory (str name) { 170 static PrimitiveCategory* findCategory( str name )
157 for (PrimitiveCategory& cat : g_PrimitiveCategories) 171 {
158 if (cat.name () == name) 172 for( PrimitiveCategory & cat : g_PrimitiveCategories )
173 if( cat.name() == name )
159 return &cat; 174 return &cat;
160 175
161 return null; 176 return null;
162 } 177 }
163 178
164 // ============================================================================= 179 // =============================================================================
165 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 180 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
166 // ============================================================================= 181 // =============================================================================
167 static void populateCategories () { 182 static void populateCategories()
168 for (PrimitiveCategory& cat : g_PrimitiveCategories) 183 {
169 cat.prims.clear (); 184 for( PrimitiveCategory & cat : g_PrimitiveCategories )
185 cat.prims.clear();
170 186
171 PrimitiveCategory* unmatched = findCategory( g_Other ); 187 PrimitiveCategory* unmatched = findCategory( g_Other );
172 188
173 if (!unmatched) { 189 if( !unmatched )
190 {
174 // Shouldn't happen.. but catch it anyway. 191 // Shouldn't happen.. but catch it anyway.
175 PrimitiveCategory cat; 192 PrimitiveCategory cat;
176 cat.setName( g_Other ); 193 cat.setName( g_Other );
177 unmatched = &(g_PrimitiveCategories << cat); 194 unmatched = &( g_PrimitiveCategories << cat );
178 } 195 }
179 196
180 for (Primitive& prim : g_primitives) { 197 for( Primitive & prim : g_primitives )
198 {
181 bool matched = false; 199 bool matched = false;
182 200
183 // Go over the categories and their regexes, if and when there's a match, 201 // Go over the categories and their regexes, if and when there's a match,
184 // the primitive's category is set to the category the regex beloings to. 202 // the primitive's category is set to the category the regex beloings to.
185 for (PrimitiveCategory& cat : g_PrimitiveCategories) { 203 for( PrimitiveCategory & cat : g_PrimitiveCategories )
186 for (PrimitiveCategory::RegexEntry& entry : cat.regexes) { 204 {
187 switch (entry.type) { 205 for( PrimitiveCategory::RegexEntry & entry : cat.regexes )
206 {
207 switch( entry.type )
208 {
188 case PrimitiveCategory::Filename: 209 case PrimitiveCategory::Filename:
189 // f-regex, check against filename 210 // f-regex, check against filename
190 matched = entry.regex.exactMatch (prim.name); 211 matched = entry.regex.exactMatch( prim.name );
191 break; 212 break;
192 213
193 case PrimitiveCategory::Title: 214 case PrimitiveCategory::Title:
194 // t-regex, check against title 215 // t-regex, check against title
195 matched = entry.regex.exactMatch (prim.title); 216 matched = entry.regex.exactMatch( prim.title );
196 break; 217 break;
197 } 218 }
198 219
199 if (matched) { 220 if( matched )
221 {
200 prim.cat = &cat; 222 prim.cat = &cat;
201 break; 223 break;
202 } 224 }
203 } 225 }
204 226
205 // Drop out if a category was decided on. 227 // Drop out if a category was decided on.
206 if (prim.cat) 228 if( prim.cat )
207 break; 229 break;
208 } 230 }
209 231
210 // If there was a match, add the primitive to the category. 232 // If there was a match, add the primitive to the category.
211 // Otherwise, add it to the list of unmatched primitives. 233 // Otherwise, add it to the list of unmatched primitives.
212 if (prim.cat) 234 if( prim.cat )
213 prim.cat->prims << prim; 235 prim.cat->prims << prim;
214 else 236 else
215 unmatched->prims << prim; 237 unmatched->prims << prim;
216 } 238 }
217 } 239 }
218 240
219 // ============================================================================= 241 // =============================================================================
220 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 242 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
221 // ============================================================================= 243 // =============================================================================
222 static void loadPrimitiveCatgories () { 244 static void loadPrimitiveCatgories()
223 g_PrimitiveCategories.clear (); 245 {
224 246 g_PrimitiveCategories.clear();
225 File f (config::dirpath () + "primregexps.cfg", File::Read); 247
226 248 File f( config::dirpath() + "primregexps.cfg", File::Read );
227 if (!f) 249
228 f.open (":/data/primitive-categories.cfg", File::Read); 250 if( !f )
229 251 f.open( ":/data/primitive-categories.cfg", File::Read );
230 if (!f) 252
253 if( !f )
231 critical( QObject::tr( "Failed to open primitive categories!" )); 254 critical( QObject::tr( "Failed to open primitive categories!" ));
232 255
233 if (f) { 256 if( f )
257 {
234 PrimitiveCategory cat; 258 PrimitiveCategory cat;
235 259
236 for (str line : f) { 260 for( str line : f )
261 {
237 int colon; 262 int colon;
238 263
239 if (line.length () == 0 || line[0] == '#') 264 if( line.length() == 0 || line[0] == '#' )
240 continue; 265 continue;
241 266
242 if ((colon = line.indexOf (":")) == -1) { 267 if( ( colon = line.indexOf( ":" )) == -1 )
243 if (cat.regexes.size () > 0) 268 {
269 if( cat.regexes.size() > 0 )
244 g_PrimitiveCategories << cat; 270 g_PrimitiveCategories << cat;
245 271
246 cat.regexes.clear (); 272 cat.regexes.clear();
247 cat.prims.clear (); 273 cat.prims.clear();
248 cat.setName (line); 274 cat.setName( line );
249 } else { 275 }
250 str cmd = line.left (colon); 276 else
277 {
278 str cmd = line.left( colon );
251 279
252 PrimitiveCategory::Type type = PrimitiveCategory::Filename; 280 PrimitiveCategory::Type type = PrimitiveCategory::Filename;
253 if (cmd == "f") { 281
282 if( cmd == "f" )
254 type = PrimitiveCategory::Filename; 283 type = PrimitiveCategory::Filename;
255 } elif (cmd == "t") { 284 elif( cmd == "t" )
256 type = PrimitiveCategory::Title; 285 type = PrimitiveCategory::Title;
257 } else 286 else
258 continue; 287 continue;
259 288
260 QRegExp regex (line.mid (colon + 1)); 289 QRegExp regex( line.mid( colon + 1 ));
261 PrimitiveCategory::RegexEntry entry = { regex, type }; 290 PrimitiveCategory::RegexEntry entry = { regex, type };
262 cat.regexes << entry; 291 cat.regexes << entry;
263 } 292 }
264 } 293 }
265 294
266 if (cat.regexes.size () > 0) 295 if( cat.regexes.size() > 0 )
267 g_PrimitiveCategories << cat; 296 g_PrimitiveCategories << cat;
268 } 297 }
269 298
270 // Add a category for unmatched primitives 299 // Add a category for unmatched primitives
271 PrimitiveCategory cat; 300 PrimitiveCategory cat;
283 { 312 {
284 vector<LDObject*> objs; 313 vector<LDObject*> objs;
285 314
286 for( int i = 0; i < segs; ++i ) 315 for( int i = 0; i < segs; ++i )
287 { 316 {
288 double x0 = cos(( i * 2 * pi ) / divs ), 317 double x0 = cos( ( i * 2 * pi ) / divs ),
289 x1 = cos((( i + 1 ) * 2 * pi) / divs ), 318 x1 = cos( ( ( i + 1 ) * 2 * pi ) / divs ),
290 z0 = sin(( i * 2 * pi ) / divs ), 319 z0 = sin( ( i * 2 * pi ) / divs ),
291 z1 = sin((( i + 1 ) * 2 * pi ) / divs ); 320 z1 = sin( ( ( i + 1 ) * 2 * pi ) / divs );
292 321
293 LDObject* obj = null; 322 LDObject* obj = null;
294 323
295 switch( type ) 324 switch( type )
296 { 325 {
297 case Circle: 326 case Circle:
298 { 327 {
299 vertex v0( x0, 0.0f, z0 ), 328 vertex v0( x0, 0.0f, z0 ),
300 v1( x1, 0.0f, z1 ); 329 v1( x1, 0.0f, z1 );
301 330
302 LDLine* line = new LDLine; 331 LDLine* line = new LDLine;
303 line->setVertex( 0, v0 ); 332 line->setVertex( 0, v0 );
304 line->setVertex( 1, v1 ); 333 line->setVertex( 1, v1 );
305 line->setColor( edgecolor ); 334 line->setColor( edgecolor );
306 obj = line; 335 obj = line;
307 } 336 }
308 break; 337 break;
309 338
310 case Cylinder: 339 case Cylinder:
311 case Ring: 340 case Ring:
312 case Cone: 341 case Cone:
342 {
343 double x2, x3, z2, z3;
344 double y0, y1, y2, y3;
345
346 if( type == Cylinder )
313 { 347 {
314 double x2, x3, z2, z3; 348 x2 = x1;
315 double y0, y1, y2, y3; 349 x3 = x0;
316 350 z2 = z1;
317 if( type == Cylinder ) 351 z3 = z0;
352
353 y0 = y1 = 0.0f;
354 y2 = y3 = 1.0f;
355 }
356 else
357 {
358 x2 = x1 * ( num + 1 );
359 x3 = x0 * ( num + 1 );
360 z2 = z1 * ( num + 1 );
361 z3 = z0 * ( num + 1 );
362
363 x0 *= num;
364 x1 *= num;
365 z0 *= num;
366 z1 *= num;
367
368 if( type == Ring )
369 y0 = y1 = y2 = y3 = 0.0f;
370 else
318 { 371 {
319 x2 = x1; 372 y0 = y1 = 1.0f;
320 x3 = x0; 373 y2 = y3 = 0.0f;
321 z2 = z1;
322 z3 = z0;
323
324 y0 = y1 = 0.0f;
325 y2 = y3 = 1.0f;
326 } else {
327 x2 = x1 * (num + 1);
328 x3 = x0 * (num + 1);
329 z2 = z1 * (num + 1);
330 z3 = z0 * (num + 1);
331
332 x0 *= num;
333 x1 *= num;
334 z0 *= num;
335 z1 *= num;
336
337 if( type == Ring )
338 y0 = y1 = y2 = y3 = 0.0f;
339 else
340 {
341 y0 = y1 = 1.0f;
342 y2 = y3 = 0.0f;
343 }
344 } 374 }
345
346 vertex v0( x0, y0, z0 ),
347 v1( x1, y1, z1 ),
348 v2( x2, y2, z2 ),
349 v3( x3, y3, z3 );
350
351 LDQuad* quad = new LDQuad;
352 quad->setColor( maincolor );
353 quad->setVertex( 0, v0 );
354 quad->setVertex( 1, v1 );
355 quad->setVertex( 2, v2 );
356 quad->setVertex( 3, v3 );
357 obj = quad;
358 } 375 }
359 break; 376
377 vertex v0( x0, y0, z0 ),
378 v1( x1, y1, z1 ),
379 v2( x2, y2, z2 ),
380 v3( x3, y3, z3 );
381
382 LDQuad* quad = new LDQuad;
383 quad->setColor( maincolor );
384 quad->setVertex( 0, v0 );
385 quad->setVertex( 1, v1 );
386 quad->setVertex( 2, v2 );
387 quad->setVertex( 3, v3 );
388 obj = quad;
389 }
390 break;
360 391
361 case Disc: 392 case Disc:
362 case DiscNeg: 393 case DiscNeg:
394 {
395 double x2, z2;
396
397 if( type == Disc )
398 x2 = z2 = 0.0f;
399 else
363 { 400 {
364 double x2, z2; 401 x2 = ( x0 >= 0.0f ) ? 1.0f : -1.0f;
365 402 z2 = ( z0 >= 0.0f ) ? 1.0f : -1.0f;
366 if( type == Disc )
367 x2 = z2 = 0.0f;
368 else
369 {
370 x2 = ( x0 >= 0.0f ) ? 1.0f : -1.0f;
371 z2 = ( z0 >= 0.0f ) ? 1.0f : -1.0f;
372 }
373
374 vertex v0( x0, 0.0f, z0 ),
375 v1( x1, 0.0f, z1 ),
376 v2( x2, 0.0f, z2 );
377
378 // Disc negatives need to go the other way around, otherwise
379 // they'll end up upside-down.
380 LDTriangle* seg = new LDTriangle;
381 seg->setColor( maincolor );
382 seg->setVertex( type == Disc ? 0 : 2, v0 );
383 seg->setVertex( 1, v1 );
384 seg->setVertex( type == Disc ? 2 : 0, v2 );
385 obj = seg;
386 } 403 }
387 break; 404
405 vertex v0( x0, 0.0f, z0 ),
406 v1( x1, 0.0f, z1 ),
407 v2( x2, 0.0f, z2 );
408
409 // Disc negatives need to go the other way around, otherwise
410 // they'll end up upside-down.
411 LDTriangle* seg = new LDTriangle;
412 seg->setColor( maincolor );
413 seg->setVertex( type == Disc ? 0 : 2, v0 );
414 seg->setVertex( 1, v1 );
415 seg->setVertex( type == Disc ? 2 : 0, v2 );
416 obj = seg;
417 }
418 break;
388 419
389 default: 420 default:
390 break; 421 break;
391 } 422 }
392 423
403 return type == Circle ? "Circle" : 434 return type == Circle ? "Circle" :
404 type == Cylinder ? "Cylinder" : 435 type == Cylinder ? "Cylinder" :
405 type == Disc ? "Disc" : 436 type == Disc ? "Disc" :
406 type == DiscNeg ? "Disc Negative" : 437 type == DiscNeg ? "Disc Negative" :
407 type == Ring ? "Ring" : 438 type == Ring ? "Ring" :
408 "Cone"; 439 "Cone";
409 } 440 }
410 441
411 static const str g_radialNameRoots[] = { 442 static const str g_radialNameRoots[] =
443 {
412 "edge", 444 "edge",
413 "cyli", 445 "cyli",
414 "disc", 446 "disc",
415 "ndis", 447 "ndis",
416 "ring", 448 "ring",
435 numer *= factor; 467 numer *= factor;
436 denom *= factor; 468 denom *= factor;
437 } 469 }
438 470
439 // Compose some general information: prefix, fraction, root, ring number 471 // Compose some general information: prefix, fraction, root, ring number
440 str prefix = (divs == lores) ? "" : fmt( "%1/", divs ); 472 str prefix = ( divs == lores ) ? "" : fmt( "%1/", divs );
441 str frac = fmt( "%1-%2", numer, denom ); 473 str frac = fmt( "%1-%2", numer, denom );
442 str root = g_radialNameRoots[type]; 474 str root = g_radialNameRoots[type];
443 str numstr = ( type == Ring || type == Cone ) ? fmt ( "%1", num ) : ""; 475 str numstr = ( type == Ring || type == Cone ) ? fmt( "%1", num ) : "";
444 476
445 // Truncate the root if necessary (7-16rin4.dat for instance). 477 // Truncate the root if necessary (7-16rin4.dat for instance).
446 // However, always keep the root at least 2 characters. 478 // However, always keep the root at least 2 characters.
447 int extra = ( frac.length() + numstr.length() + root.length() ) - 8; 479 int extra = ( frac.length() + numstr.length() + root.length()) - 8;
448 root.chop( min<short>( max<short>( extra, 0 ), 2 )); 480 root.chop( min<short>( max<short>( extra, 0 ), 2 ));
449 481
450 // Stick them all together and return the result. 482 // Stick them all together and return the result.
451 return prefix + frac + root + numstr + ".dat"; 483 return prefix + frac + root + numstr + ".dat";
452 } 484 }
469 PrimitiveType type = 501 PrimitiveType type =
470 ui.rb_circle->isChecked() ? Circle : 502 ui.rb_circle->isChecked() ? Circle :
471 ui.rb_cylinder->isChecked() ? Cylinder : 503 ui.rb_cylinder->isChecked() ? Cylinder :
472 ui.rb_disc->isChecked() ? Disc : 504 ui.rb_disc->isChecked() ? Disc :
473 ui.rb_ndisc->isChecked() ? DiscNeg : 505 ui.rb_ndisc->isChecked() ? DiscNeg :
474 ui.rb_ring->isChecked() ? Ring : 506 ui.rb_ring->isChecked() ? Ring : Cone;
475 Cone;
476 507
477 // Make the description 508 // Make the description
478 str frac = ftoa(( (float) segs ) / divs ); 509 str frac = ftoa( ( ( float ) segs ) / divs );
479 str name = radialFileName( type, segs, divs, num ); 510 str name = radialFileName( type, segs, divs, num );
480 str descr; 511 str descr;
481 512
482 // Ensure that there's decimals, even if they're 0. 513 // Ensure that there's decimals, even if they're 0.
483 if( frac.indexOf( "." ) == -1 ) 514 if( frac.indexOf( "." ) == -1 )
484 frac += ".0"; 515 frac += ".0";
485 516
486 if (type == Ring || type == Cone) 517 if( type == Ring || type == Cone )
487 descr = fmt( "%1 %2 x %3", primitiveTypeName( type ), num, frac ); 518 descr = fmt( "%1 %2 x %3", primitiveTypeName( type ), num, frac );
488 else 519 else
489 descr = fmt( "%1 %2", primitiveTypeName( type ), frac ); 520 descr = fmt( "%1 %2", primitiveTypeName( type ), frac );
490 521
491 LDOpenFile* f = new LDOpenFile; 522 LDOpenFile* f = new LDOpenFile;

mercurial