38 cfg (Bool, edit_schemanticinline, false); |
38 cfg (Bool, edit_schemanticinline, false); |
39 extern_cfg (String, ld_defaultuser); |
39 extern_cfg (String, ld_defaultuser); |
40 |
40 |
41 // ============================================================================= |
41 // ============================================================================= |
42 // ----------------------------------------------------------------------------- |
42 // ----------------------------------------------------------------------------- |
43 static int copyToClipboard() { |
43 static int copyToClipboard() |
44 List<LDObject*> objs = g_win->sel(); |
44 { List<LDObject*> objs = g_win->sel(); |
45 int num = 0; |
45 int num = 0; |
46 |
46 |
47 // Clear the clipboard first. |
47 // Clear the clipboard first. |
48 qApp->clipboard()->clear(); |
48 qApp->clipboard()->clear(); |
49 |
49 |
50 // Now, copy the contents into the clipboard. |
50 // Now, copy the contents into the clipboard. |
51 str data; |
51 str data; |
52 |
52 |
53 for (LDObject* obj : objs) { |
53 for (LDObject* obj : objs) |
54 if (data.length() > 0) |
54 { if (data.length() > 0) |
55 data += "\n"; |
55 data += "\n"; |
56 |
56 |
57 data += obj->raw(); |
57 data += obj->raw(); |
58 ++num; |
58 ++num; |
59 } |
59 } |
60 |
60 |
61 qApp->clipboard()->setText (data); |
61 qApp->clipboard()->setText (data); |
62 return num; |
62 return num; |
63 } |
63 } |
64 |
64 |
65 // ============================================================================= |
65 // ============================================================================= |
66 // ----------------------------------------------------------------------------- |
66 // ----------------------------------------------------------------------------- |
67 DEFINE_ACTION (Cut, CTRL (X)) { |
67 DEFINE_ACTION (Cut, CTRL (X)) |
68 int num = copyToClipboard(); |
68 { int num = copyToClipboard(); |
69 g_win->deleteSelection(); |
69 g_win->deleteSelection(); |
70 log (ForgeWindow::tr ("%1 objects cut"), num); |
70 log (ForgeWindow::tr ("%1 objects cut"), num); |
71 } |
71 } |
72 |
72 |
73 // ============================================================================= |
73 // ============================================================================= |
74 // ----------------------------------------------------------------------------- |
74 // ----------------------------------------------------------------------------- |
75 DEFINE_ACTION (Copy, CTRL (C)) { |
75 DEFINE_ACTION (Copy, CTRL (C)) |
76 int num = copyToClipboard(); |
76 { int num = copyToClipboard(); |
77 log (ForgeWindow::tr ("%1 objects copied"), num); |
77 log (ForgeWindow::tr ("%1 objects copied"), num); |
78 } |
78 } |
79 |
79 |
80 // ============================================================================= |
80 // ============================================================================= |
81 // ----------------------------------------------------------------------------- |
81 // ----------------------------------------------------------------------------- |
82 DEFINE_ACTION (Paste, CTRL (V)) { |
82 DEFINE_ACTION (Paste, CTRL (V)) |
83 const str clipboardText = qApp->clipboard()->text(); |
83 { const str clipboardText = qApp->clipboard()->text(); |
84 ulong idx = g_win->getInsertionPoint(); |
84 ulong idx = g_win->getInsertionPoint(); |
85 g_win->sel().clear(); |
85 g_win->sel().clear(); |
86 int num = 0; |
86 int num = 0; |
87 |
87 |
88 for (str line : clipboardText.split ("\n")) { |
88 for (str line : clipboardText.split ("\n")) |
89 LDObject* pasted = parseLine (line); |
89 { LDObject* pasted = parseLine (line); |
90 LDFile::current()->insertObj (idx++, pasted); |
90 LDFile::current()->insertObj (idx++, pasted); |
91 g_win->sel() << pasted; |
91 g_win->sel() << pasted; |
92 g_win->R()->compileObject (pasted); |
92 g_win->R()->compileObject (pasted); |
93 ++num; |
93 ++num; |
94 } |
94 } |
95 |
95 |
96 log (ForgeWindow::tr ("%1 objects pasted"), num); |
96 log (ForgeWindow::tr ("%1 objects pasted"), num); |
97 g_win->refresh(); |
97 g_win->refresh(); |
98 g_win->scrollToSelection(); |
98 g_win->scrollToSelection(); |
99 } |
99 } |
100 |
100 |
101 // ============================================================================= |
101 // ============================================================================= |
102 // ----------------------------------------------------------------------------- |
102 // ----------------------------------------------------------------------------- |
103 DEFINE_ACTION (Delete, KEY (Delete)) { |
103 DEFINE_ACTION (Delete, KEY (Delete)) |
104 int num = g_win->deleteSelection(); |
104 { int num = g_win->deleteSelection(); |
105 log (ForgeWindow::tr ("%1 objects deleted"), num); |
105 log (ForgeWindow::tr ("%1 objects deleted"), num); |
106 } |
106 } |
107 |
107 |
108 // ============================================================================= |
108 // ============================================================================= |
109 // ----------------------------------------------------------------------------- |
109 // ----------------------------------------------------------------------------- |
110 static void doInline (bool deep) { |
110 static void doInline (bool deep) |
111 List<LDObject*> sel = g_win->sel(); |
111 { List<LDObject*> sel = g_win->sel(); |
112 |
112 |
113 for (LDObject* obj : sel) { |
113 for (LDObject* obj : sel) |
114 // Get the index of the subfile so we know where to insert the |
114 { // Get the index of the subfile so we know where to insert the |
115 // inlined contents. |
115 // inlined contents. |
116 long idx = obj->getIndex(); |
116 long idx = obj->getIndex(); |
117 |
117 |
118 if (idx == -1) |
118 if (idx == -1) |
119 continue; |
119 continue; |
120 |
120 |
121 List<LDObject*> objs; |
121 List<LDObject*> objs; |
122 |
122 |
123 if (obj->getType() == LDObject::Subfile) |
123 if (obj->getType() == LDObject::Subfile) |
124 objs = static_cast<LDSubfile*> (obj)->inlineContents ( |
124 objs = static_cast<LDSubfile*> (obj)->inlineContents ( |
125 (LDSubfile::InlineFlags) |
125 (LDSubfile::InlineFlags) |
126 ((deep) ? LDSubfile::DeepInline : 0) | |
126 ( (deep) ? LDSubfile::DeepInline : 0) | |
127 LDSubfile::CacheInline |
127 LDSubfile::CacheInline |
128 ); |
128 ); |
129 else |
129 else |
130 continue; |
130 continue; |
131 |
131 |
132 // Merge in the inlined objects |
132 // Merge in the inlined objects |
133 for (LDObject* inlineobj : objs) { |
133 for (LDObject * inlineobj : objs) |
134 str line = inlineobj->raw(); |
134 { str line = inlineobj->raw(); |
135 delete inlineobj; |
135 delete inlineobj; |
136 |
136 |
137 LDObject* newobj = parseLine (line); |
137 LDObject* newobj = parseLine (line); |
138 LDFile::current()->insertObj (idx++, newobj); |
138 LDFile::current()->insertObj (idx++, newobj); |
139 g_win->sel() << newobj; |
139 g_win->sel() << newobj; |
140 g_win->R()->compileObject (newobj); |
140 g_win->R()->compileObject (newobj); |
141 } |
141 } |
142 |
142 |
143 // Delete the subfile now as it's been inlined. |
143 // Delete the subfile now as it's been inlined. |
144 LDFile::current()->forgetObject (obj); |
144 LDFile::current()->forgetObject (obj); |
145 delete obj; |
145 delete obj; |
146 } |
146 } |
147 |
147 |
148 g_win->refresh(); |
148 g_win->refresh(); |
149 } |
149 } |
150 |
150 |
151 DEFINE_ACTION (Inline, CTRL (I)) { |
151 DEFINE_ACTION (Inline, CTRL (I)) |
152 doInline (false); |
152 { doInline (false); |
153 } |
153 } |
154 |
154 |
155 DEFINE_ACTION (InlineDeep, CTRL_SHIFT (I)) { |
155 DEFINE_ACTION (InlineDeep, CTRL_SHIFT (I)) |
156 doInline (true); |
156 { doInline (true); |
157 } |
157 } |
158 |
158 |
159 // ============================================================================= |
159 // ============================================================================= |
160 // ----------------------------------------------------------------------------- |
160 // ----------------------------------------------------------------------------- |
161 DEFINE_ACTION (SplitQuads, 0) { |
161 DEFINE_ACTION (SplitQuads, 0) |
162 List<LDObject*> objs = g_win->sel(); |
162 { List<LDObject*> objs = g_win->sel(); |
163 int num = 0; |
163 int num = 0; |
164 |
164 |
165 for (LDObject* obj : objs) { |
165 for (LDObject* obj : objs) |
166 if (obj->getType() != LDObject::Quad) |
166 { if (obj->getType() != LDObject::Quad) |
167 continue; |
167 continue; |
168 |
168 |
169 // Find the index of this quad |
169 // Find the index of this quad |
170 long index = obj->getIndex(); |
170 long index = obj->getIndex(); |
171 |
171 |
172 if (index == -1) |
172 if (index == -1) |
173 return; |
173 return; |
174 |
174 |
175 List<LDTriangle*> triangles = static_cast<LDQuad*> (obj)->splitToTriangles(); |
175 List<LDTriangle*> triangles = static_cast<LDQuad*> (obj)->splitToTriangles(); |
176 |
176 |
177 // Replace the quad with the first triangle and add the second triangle |
177 // Replace the quad with the first triangle and add the second triangle |
178 // after the first one. |
178 // after the first one. |
179 LDFile::current()->setObject (index, triangles[0]); |
179 LDFile::current()->setObject (index, triangles[0]); |
180 LDFile::current()->insertObj (index + 1, triangles[1]); |
180 LDFile::current()->insertObj (index + 1, triangles[1]); |
181 |
181 |
182 for (LDTriangle * t : triangles) |
182 for (LDTriangle* t : triangles) |
183 g_win->R()->compileObject (t); |
183 g_win->R()->compileObject (t); |
184 |
184 |
185 // Delete this quad now, it has been split. |
185 // Delete this quad now, it has been split. |
186 delete obj; |
186 delete obj; |
187 |
187 |
188 num++; |
188 num++; |
189 } |
189 } |
190 |
190 |
191 log ("%1 quadrilaterals split", num); |
191 log ("%1 quadrilaterals split", num); |
192 g_win->refresh(); |
192 g_win->refresh(); |
193 } |
193 } |
194 |
194 |
195 // ============================================================================= |
195 // ============================================================================= |
196 // ----------------------------------------------------------------------------- |
196 // ----------------------------------------------------------------------------- |
197 DEFINE_ACTION (EditRaw, KEY (F9)) { |
197 DEFINE_ACTION (EditRaw, KEY (F9)) |
198 if (g_win->sel().size() != 1) |
198 { if (g_win->sel().size() != 1) |
199 return; |
199 return; |
200 |
200 |
201 LDObject* obj = g_win->sel() [0]; |
201 LDObject* obj = g_win->sel() [0]; |
202 QDialog* dlg = new QDialog; |
202 QDialog* dlg = new QDialog; |
203 Ui::EditRawUI ui; |
203 Ui::EditRawUI ui; |
204 |
204 |
205 ui.setupUi (dlg); |
205 ui.setupUi (dlg); |
206 ui.code->setText (obj->raw()); |
206 ui.code->setText (obj->raw()); |
207 |
207 |
208 if (obj->getType() == LDObject::Error) |
208 if (obj->getType() == LDObject::Error) |
209 ui.errorDescription->setText (static_cast<LDError*> (obj)->reason); |
209 ui.errorDescription->setText (static_cast<LDError*> (obj)->reason); |
210 else { |
210 else |
211 ui.errorDescription->hide(); |
211 { ui.errorDescription->hide(); |
212 ui.errorIcon->hide(); |
212 ui.errorIcon->hide(); |
213 } |
213 } |
214 |
214 |
215 if (!dlg->exec()) |
215 if (!dlg->exec()) |
216 return; |
216 return; |
217 |
217 |
218 LDObject* oldobj = obj; |
218 LDObject* oldobj = obj; |
219 |
219 |
220 // Reinterpret it from the text of the input field |
220 // Reinterpret it from the text of the input field |
221 obj = parseLine (ui.code->text()); |
221 obj = parseLine (ui.code->text()); |
222 oldobj->replace (obj); |
222 oldobj->replace (obj); |
223 |
223 |
224 // Refresh |
224 // Refresh |
225 g_win->R()->compileObject (obj); |
225 g_win->R()->compileObject (obj); |
226 g_win->refresh(); |
226 g_win->refresh(); |
227 } |
227 } |
228 |
228 |
229 // ============================================================================= |
229 // ============================================================================= |
230 // ----------------------------------------------------------------------------- |
230 // ----------------------------------------------------------------------------- |
231 DEFINE_ACTION (SetColor, KEY (C)) { |
231 DEFINE_ACTION (SetColor, KEY (C)) |
232 if (g_win->sel().size() <= 0) |
232 { if (g_win->sel().size() <= 0) |
233 return; |
233 return; |
234 |
234 |
235 short colnum; |
235 short colnum; |
236 short defcol = -1; |
236 short defcol = -1; |
237 |
237 |
238 List<LDObject*> objs = g_win->sel(); |
238 List<LDObject*> objs = g_win->sel(); |
239 |
239 |
240 // If all selected objects have the same color, said color is our default |
240 // If all selected objects have the same color, said color is our default |
241 // value to the color selection dialog. |
241 // value to the color selection dialog. |
242 defcol = g_win->getSelectedColor(); |
242 defcol = g_win->getSelectedColor(); |
243 |
243 |
244 // Show the dialog to the user now and ask for a color. |
244 // Show the dialog to the user now and ask for a color. |
245 if (ColorSelector::getColor (colnum, defcol, g_win)) { |
245 if (ColorSelector::getColor (colnum, defcol, g_win)) |
246 for (LDObject* obj : objs) { |
246 { for (LDObject* obj : objs) |
247 if (obj->isColored() == false) |
247 { if (obj->isColored() == false) |
248 continue; |
248 continue; |
249 |
249 |
250 obj->setColor (colnum); |
250 obj->setColor (colnum); |
251 g_win->R()->compileObject (obj); |
251 g_win->R()->compileObject (obj); |
252 } |
252 } |
253 |
253 |
254 g_win->refresh(); |
254 g_win->refresh(); |
255 } |
255 } |
256 } |
256 } |
257 |
257 |
258 // ============================================================================= |
258 // ============================================================================= |
259 // ----------------------------------------------------------------------------- |
259 // ----------------------------------------------------------------------------- |
260 DEFINE_ACTION (Borders, CTRL_SHIFT (B)) { |
260 DEFINE_ACTION (Borders, CTRL_SHIFT (B)) |
261 List<LDObject*> objs = g_win->sel(); |
261 { List<LDObject*> objs = g_win->sel(); |
262 int num = 0; |
262 int num = 0; |
263 |
263 |
264 for (LDObject* obj : objs) { |
264 for (LDObject* obj : objs) |
265 if (obj->getType() != LDObject::Quad && obj->getType() != LDObject::Triangle) |
265 { if (obj->getType() != LDObject::Quad && obj->getType() != LDObject::Triangle) |
266 continue; |
266 continue; |
267 |
267 |
268 short numLines; |
268 short numLines; |
269 LDLine* lines[4]; |
269 LDLine* lines[4]; |
270 |
270 |
271 if (obj->getType() == LDObject::Quad) { |
271 if (obj->getType() == LDObject::Quad) |
272 numLines = 4; |
272 { numLines = 4; |
273 |
273 |
274 LDQuad* quad = static_cast<LDQuad*> (obj); |
274 LDQuad* quad = static_cast<LDQuad*> (obj); |
275 lines[0] = new LDLine (quad->getVertex (0), quad->getVertex (1)); |
275 lines[0] = new LDLine (quad->getVertex (0), quad->getVertex (1)); |
276 lines[1] = new LDLine (quad->getVertex (1), quad->getVertex (2)); |
276 lines[1] = new LDLine (quad->getVertex (1), quad->getVertex (2)); |
277 lines[2] = new LDLine (quad->getVertex (2), quad->getVertex (3)); |
277 lines[2] = new LDLine (quad->getVertex (2), quad->getVertex (3)); |
278 lines[3] = new LDLine (quad->getVertex (3), quad->getVertex (0)); |
278 lines[3] = new LDLine (quad->getVertex (3), quad->getVertex (0)); |
279 } else { |
279 } |
280 numLines = 3; |
280 else |
281 |
281 { numLines = 3; |
|
282 |
282 LDTriangle* tri = static_cast<LDTriangle*> (obj); |
283 LDTriangle* tri = static_cast<LDTriangle*> (obj); |
283 lines[0] = new LDLine (tri->getVertex (0), tri->getVertex (1)); |
284 lines[0] = new LDLine (tri->getVertex (0), tri->getVertex (1)); |
284 lines[1] = new LDLine (tri->getVertex (1), tri->getVertex (2)); |
285 lines[1] = new LDLine (tri->getVertex (1), tri->getVertex (2)); |
285 lines[2] = new LDLine (tri->getVertex (2), tri->getVertex (0)); |
286 lines[2] = new LDLine (tri->getVertex (2), tri->getVertex (0)); |
286 } |
287 } |
287 |
288 |
288 for (short i = 0; i < numLines; ++i) { |
289 for (short i = 0; i < numLines; ++i) |
289 ulong idx = obj->getIndex() + i + 1; |
290 { long idx = obj->getIndex() + i + 1; |
290 |
291 |
291 lines[i]->setColor (edgecolor); |
292 lines[i]->setColor (edgecolor); |
292 LDFile::current()->insertObj (idx, lines[i]); |
293 LDFile::current()->insertObj (idx, lines[i]); |
293 g_win->R()->compileObject (lines[i]); |
294 g_win->R()->compileObject (lines[i]); |
294 } |
295 } |
295 |
296 |
296 num += numLines; |
297 num += numLines; |
297 } |
298 } |
298 |
299 |
299 log (ForgeWindow::tr ("Added %1 border lines"), num); |
300 log (ForgeWindow::tr ("Added %1 border lines"), num); |
300 g_win->refresh(); |
301 g_win->refresh(); |
301 } |
302 } |
302 |
303 |
303 // ============================================================================= |
304 // ============================================================================= |
304 // ----------------------------------------------------------------------------- |
305 // ----------------------------------------------------------------------------- |
305 DEFINE_ACTION (CornerVerts, 0) { |
306 DEFINE_ACTION (CornerVerts, 0) |
306 int num = 0; |
307 { int num = 0; |
307 |
308 |
308 for (LDObject* obj : g_win->sel()) { |
309 for (LDObject* obj : g_win->sel()) |
309 if (obj->vertices() < 2) |
310 { if (obj->vertices() < 2) |
310 continue; |
311 continue; |
311 |
312 |
312 ulong idx = obj->getIndex(); |
313 ulong idx = obj->getIndex(); |
313 |
314 |
314 for (short i = 0; i < obj->vertices(); ++i) { |
315 for (short i = 0; i < obj->vertices(); ++i) |
315 LDVertex* vert = new LDVertex; |
316 { LDVertex* vert = new LDVertex; |
316 vert->pos = obj->getVertex (i); |
317 vert->pos = obj->getVertex (i); |
317 vert->setColor (obj->color()); |
318 vert->setColor (obj->color()); |
318 |
319 |
319 LDFile::current()->insertObj (++idx, vert); |
320 LDFile::current()->insertObj (++idx, vert); |
320 g_win->R()->compileObject (vert); |
321 g_win->R()->compileObject (vert); |
321 ++num; |
322 ++num; |
322 } |
323 } |
323 } |
324 } |
324 |
325 |
325 log (ForgeWindow::tr ("Added %1 vertices"), num); |
326 log (ForgeWindow::tr ("Added %1 vertices"), num); |
326 g_win->refresh(); |
327 g_win->refresh(); |
327 } |
328 } |
328 |
329 |
329 // ============================================================================= |
330 // ============================================================================= |
330 // ----------------------------------------------------------------------------- |
331 // ----------------------------------------------------------------------------- |
331 static void doMoveSelection (const bool up) { |
332 static void doMoveSelection (const bool up) |
332 List<LDObject*> objs = g_win->sel(); |
333 { List<LDObject*> objs = g_win->sel(); |
333 LDObject::moveObjects (objs, up); |
334 LDObject::moveObjects (objs, up); |
334 g_win->buildObjList(); |
335 g_win->buildObjList(); |
335 } |
336 } |
336 |
337 |
337 // ============================================================================= |
338 // ============================================================================= |
338 // ----------------------------------------------------------------------------- |
339 // ----------------------------------------------------------------------------- |
339 DEFINE_ACTION (MoveUp, KEY (PageUp)) { |
340 DEFINE_ACTION (MoveUp, KEY (PageUp)) |
340 doMoveSelection (true); |
341 { doMoveSelection (true); |
341 } |
342 } |
342 |
343 |
343 DEFINE_ACTION (MoveDown, KEY (PageDown)) { |
344 DEFINE_ACTION (MoveDown, KEY (PageDown)) |
344 doMoveSelection (false); |
345 { doMoveSelection (false); |
345 } |
346 } |
346 |
347 |
347 // ============================================================================= |
348 // ============================================================================= |
348 // ----------------------------------------------------------------------------- |
349 // ----------------------------------------------------------------------------- |
349 DEFINE_ACTION (Undo, CTRL (Z)) { |
350 DEFINE_ACTION (Undo, CTRL (Z)) |
350 LDFile::current()->undo(); |
351 { LDFile::current()->undo(); |
351 } |
352 } |
352 |
353 |
353 DEFINE_ACTION (Redo, CTRL_SHIFT (Z)) { |
354 DEFINE_ACTION (Redo, CTRL_SHIFT (Z)) |
354 LDFile::current()->redo(); |
355 { LDFile::current()->redo(); |
355 } |
356 } |
356 |
357 |
357 // ============================================================================= |
358 // ============================================================================= |
358 // ----------------------------------------------------------------------------- |
359 // ----------------------------------------------------------------------------- |
359 void doMoveObjects (vertex vect) { |
360 void doMoveObjects (vertex vect) |
360 // Apply the grid values |
361 { // Apply the grid values |
361 vect[X] *= currentGrid().confs[Grid::X]->value; |
362 vect[X] *= currentGrid().confs[Grid::X]->value; |
362 vect[Y] *= currentGrid().confs[Grid::Y]->value; |
363 vect[Y] *= currentGrid().confs[Grid::Y]->value; |
363 vect[Z] *= currentGrid().confs[Grid::Z]->value; |
364 vect[Z] *= currentGrid().confs[Grid::Z]->value; |
364 |
365 |
365 for (LDObject* obj : g_win->sel()) { |
366 for (LDObject* obj : g_win->sel()) |
366 obj->move (vect); |
367 { obj->move (vect); |
367 g_win->R()->compileObject (obj); |
368 g_win->R()->compileObject (obj); |
368 } |
369 } |
369 |
370 |
370 g_win->refresh(); |
371 g_win->refresh(); |
371 } |
372 } |
372 |
373 |
373 // ============================================================================= |
374 // ============================================================================= |
374 // ----------------------------------------------------------------------------- |
375 // ----------------------------------------------------------------------------- |
375 DEFINE_ACTION (MoveXNeg, KEY (Left)) { |
376 DEFINE_ACTION (MoveXNeg, KEY (Left)) |
376 doMoveObjects ({-1, 0, 0}); |
377 { doMoveObjects ( { -1, 0, 0}); |
377 } |
378 } |
378 |
379 |
379 DEFINE_ACTION (MoveYNeg, KEY (Home)) { |
380 DEFINE_ACTION (MoveYNeg, KEY (Home)) |
380 doMoveObjects ({0, -1, 0}); |
381 { doMoveObjects ( {0, -1, 0}); |
381 } |
382 } |
382 |
383 |
383 DEFINE_ACTION (MoveZNeg, KEY (Down)) { |
384 DEFINE_ACTION (MoveZNeg, KEY (Down)) |
384 doMoveObjects ({0, 0, -1}); |
385 { doMoveObjects ( {0, 0, -1}); |
385 } |
386 } |
386 |
387 |
387 DEFINE_ACTION (MoveXPos, KEY (Right)) { |
388 DEFINE_ACTION (MoveXPos, KEY (Right)) |
388 doMoveObjects ({1, 0, 0}); |
389 { doMoveObjects ( {1, 0, 0}); |
389 } |
390 } |
390 |
391 |
391 DEFINE_ACTION (MoveYPos, KEY (End)) { |
392 DEFINE_ACTION (MoveYPos, KEY (End)) |
392 doMoveObjects ({0, 1, 0}); |
393 { doMoveObjects ( {0, 1, 0}); |
393 } |
394 } |
394 |
395 |
395 DEFINE_ACTION (MoveZPos, KEY (Up)) { |
396 DEFINE_ACTION (MoveZPos, KEY (Up)) |
396 doMoveObjects ({0, 0, 1}); |
397 { doMoveObjects ( {0, 0, 1}); |
397 } |
398 } |
398 |
399 |
399 // ============================================================================= |
400 // ============================================================================= |
400 // ----------------------------------------------------------------------------- |
401 // ----------------------------------------------------------------------------- |
401 DEFINE_ACTION (Invert, CTRL_SHIFT (W)) { |
402 DEFINE_ACTION (Invert, CTRL_SHIFT (W)) |
402 List<LDObject*> sel = g_win->sel(); |
403 { List<LDObject*> sel = g_win->sel(); |
403 |
404 |
404 for (LDObject* obj : sel) { |
405 for (LDObject* obj : sel) |
405 obj->invert(); |
406 { obj->invert(); |
406 g_win->R()->compileObject (obj); |
407 g_win->R()->compileObject (obj); |
407 } |
408 } |
408 |
409 |
409 g_win->refresh(); |
410 g_win->refresh(); |
410 } |
411 } |
411 |
412 |
412 // ============================================================================= |
413 // ============================================================================= |
413 // ----------------------------------------------------------------------------- |
414 // ----------------------------------------------------------------------------- |
414 static void rotateVertex (vertex& v, const vertex& rotpoint, const matrix& transform) { |
415 static void rotateVertex (vertex& v, const vertex& rotpoint, const matrix& transform) |
415 v.move (-rotpoint); |
416 { v.move (-rotpoint); |
416 v.transform (transform, g_origin); |
417 v.transform (transform, g_origin); |
417 v.move (rotpoint); |
418 v.move (rotpoint); |
418 } |
419 } |
419 |
420 |
420 // ============================================================================= |
421 // ============================================================================= |
421 // ----------------------------------------------------------------------------- |
422 // ----------------------------------------------------------------------------- |
422 static void doRotate (const short l, const short m, const short n) { |
423 static void doRotate (const short l, const short m, const short n) |
423 List<LDObject*> sel = g_win->sel(); |
424 { List<LDObject*> sel = g_win->sel(); |
424 List<vertex*> queue; |
425 List<vertex*> queue; |
425 const vertex rotpoint = rotPoint (sel); |
426 const vertex rotpoint = rotPoint (sel); |
426 const double angle = (pi * currentGrid().confs[Grid::Angle]->value) / 180, |
427 const double angle = (pi * currentGrid().confs[Grid::Angle]->value) / 180, |
427 cosangle = cos (angle), |
428 cosangle = cos (angle), |
428 sinangle = sin (angle); |
429 sinangle = sin (angle); |
429 |
430 |
430 // ref: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation_2 |
431 // ref: http://en.wikipedia.org/wiki/Transformation_matrix#Rotation_2 |
431 matrix transform ({ |
432 matrix transform ( |
432 (l * l * (1 - cosangle)) + cosangle, |
433 { (l* l * (1 - cosangle)) + cosangle, |
433 (m * l * (1 - cosangle)) - (n * sinangle), |
434 (m* l * (1 - cosangle)) - (n* sinangle), |
434 (n * l * (1 - cosangle)) + (m * sinangle), |
435 (n* l * (1 - cosangle)) + (m* sinangle), |
435 |
436 |
436 (l * m * (1 - cosangle)) + (n * sinangle), |
437 (l* m * (1 - cosangle)) + (n* sinangle), |
437 (m * m * (1 - cosangle)) + cosangle, |
438 (m* m * (1 - cosangle)) + cosangle, |
438 (n * m * (1 - cosangle)) - (l * sinangle), |
439 (n* m * (1 - cosangle)) - (l* sinangle), |
439 |
440 |
440 (l * n * (1 - cosangle)) - (m * sinangle), |
441 (l* n * (1 - cosangle)) - (m* sinangle), |
441 (m * n * (1 - cosangle)) + (l * sinangle), |
442 (m* n * (1 - cosangle)) + (l* sinangle), |
442 (n * n * (1 - cosangle)) + cosangle |
443 (n* n * (1 - cosangle)) + cosangle |
443 }); |
444 }); |
444 |
445 |
445 // Apply the above matrix to everything |
446 // Apply the above matrix to everything |
446 for (LDObject* obj : sel) { |
447 for (LDObject* obj : sel) |
447 if (obj->vertices()) { |
448 { if (obj->vertices()) |
448 for (short i = 0; i < obj->vertices(); ++i) { |
449 { for (short i = 0; i < obj->vertices(); ++i) |
449 vertex v = obj->getVertex (i); |
450 { vertex v = obj->getVertex (i); |
450 rotateVertex (v, rotpoint, transform); |
451 rotateVertex (v, rotpoint, transform); |
451 obj->setVertex (i, v); |
452 obj->setVertex (i, v); |
452 } |
453 } |
453 } elif (obj->hasMatrix()) { |
454 } elif (obj->hasMatrix()) |
454 LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (obj); |
455 |
455 |
456 { LDMatrixObject* mo = dynamic_cast<LDMatrixObject*> (obj); |
|
457 |
456 // Transform the position |
458 // Transform the position |
457 vertex v = mo->position(); |
459 vertex v = mo->position(); |
458 rotateVertex (v, rotpoint, transform); |
460 rotateVertex (v, rotpoint, transform); |
459 mo->setPosition (v); |
461 mo->setPosition (v); |
460 |
462 |
461 // Transform the matrix |
463 // Transform the matrix |
462 mo->setTransform (mo->transform() * transform); |
464 mo->setTransform (mo->transform() * transform); |
463 } elif (obj->getType() == LDObject::Vertex) { |
465 } elif (obj->getType() == LDObject::Vertex) |
464 LDVertex* vert = static_cast<LDVertex*> (obj); |
466 { LDVertex* vert = static_cast<LDVertex*> (obj); |
465 vertex v = vert->pos; |
467 vertex v = vert->pos; |
466 rotateVertex (v, rotpoint, transform); |
468 rotateVertex (v, rotpoint, transform); |
467 vert->pos = v; |
469 vert->pos = v; |
468 } |
470 } |
469 |
471 |
470 g_win->R()->compileObject (obj); |
472 g_win->R()->compileObject (obj); |
471 } |
473 } |
472 |
474 |
473 g_win->refresh(); |
475 g_win->refresh(); |
474 } |
476 } |
475 |
477 |
476 // ============================================================================= |
478 // ============================================================================= |
477 // ----------------------------------------------------------------------------- |
479 // ----------------------------------------------------------------------------- |
478 DEFINE_ACTION (RotateXPos, CTRL (Right)) { doRotate (1, 0, 0); } |
480 DEFINE_ACTION (RotateXPos, CTRL (Right)) |
479 DEFINE_ACTION (RotateYPos, CTRL (End)) { doRotate (0, 1, 0); } |
481 { doRotate (1, 0, 0); |
480 DEFINE_ACTION (RotateZPos, CTRL (Up)) { doRotate (0, 0, 1); } |
482 } |
481 DEFINE_ACTION (RotateXNeg, CTRL (Left)) { doRotate (-1, 0, 0); } |
483 DEFINE_ACTION (RotateYPos, CTRL (End)) |
482 DEFINE_ACTION (RotateYNeg, CTRL (Home)) { doRotate (0, -1, 0); } |
484 { doRotate (0, 1, 0); |
483 DEFINE_ACTION (RotateZNeg, CTRL (Down)) { doRotate (0, 0, -1); } |
485 } |
484 |
486 DEFINE_ACTION (RotateZPos, CTRL (Up)) |
485 DEFINE_ACTION (RotationPoint, (0)) { |
487 { doRotate (0, 0, 1); |
486 configRotationPoint(); |
488 } |
487 } |
489 DEFINE_ACTION (RotateXNeg, CTRL (Left)) |
488 |
490 { doRotate (-1, 0, 0); |
489 // ============================================================================= |
491 } |
490 // ----------------------------------------------------------------------------- |
492 DEFINE_ACTION (RotateYNeg, CTRL (Home)) |
491 DEFINE_ACTION (RoundCoordinates, 0) { |
493 { doRotate (0, -1, 0); |
492 setlocale (LC_ALL, "C"); |
494 } |
|
495 DEFINE_ACTION (RotateZNeg, CTRL (Down)) |
|
496 { doRotate (0, 0, -1); |
|
497 } |
|
498 |
|
499 DEFINE_ACTION (RotationPoint, (0)) |
|
500 { configRotationPoint(); |
|
501 } |
|
502 |
|
503 // ============================================================================= |
|
504 // ----------------------------------------------------------------------------- |
|
505 DEFINE_ACTION (RoundCoordinates, 0) |
|
506 { setlocale (LC_ALL, "C"); |
493 int num = 0; |
507 int num = 0; |
494 |
508 |
495 for (LDObject* obj : g_win->sel()) |
509 for (LDObject* obj : g_win->sel()) |
496 for (short i = 0; i < obj->vertices(); ++i) { |
510 for (short i = 0; i < obj->vertices(); ++i) |
497 vertex v = obj->getVertex (i); |
511 { vertex v = obj->getVertex (i); |
498 |
512 |
499 for (const Axis ax : g_Axes) { |
513 for (const Axis ax : g_Axes) |
500 // HACK: .. should find a better way to do this |
514 { // HACK: .. should find a better way to do this |
501 char valstr[64]; |
515 char valstr[64]; |
502 sprintf (valstr, "%.3f", v[ax]); |
516 sprintf (valstr, "%.3f", v[ax]); |
503 v[ax] = atof (valstr); |
517 v[ax] = atof (valstr); |
504 } |
518 } |
505 |
519 |
506 obj->setVertex (i, v); |
520 obj->setVertex (i, v); |
507 g_win->R()->compileObject (obj); |
521 g_win->R()->compileObject (obj); |
508 num += 3; |
522 num += 3; |
509 } |
523 } |
510 |
524 |
511 log (ForgeWindow::tr ("Rounded %1 coordinates"), num); |
525 log (ForgeWindow::tr ("Rounded %1 coordinates"), num); |
512 g_win->refresh(); |
526 g_win->refresh(); |
513 } |
527 } |
514 |
528 |
515 // ============================================================================= |
529 // ============================================================================= |
516 // ----------------------------------------------------------------------------- |
530 // ----------------------------------------------------------------------------- |
517 DEFINE_ACTION (Uncolorize, 0) { |
531 DEFINE_ACTION (Uncolorize, 0) |
518 int num = 0; |
532 { int num = 0; |
519 |
533 |
520 for (LDObject* obj : g_win->sel()) { |
534 for (LDObject* obj : g_win->sel()) |
521 if (obj->isColored() == false) |
535 { if (obj->isColored() == false) |
522 continue; |
536 continue; |
523 |
537 |
524 int col = maincolor; |
538 int col = maincolor; |
525 |
539 |
526 if (obj->getType() == LDObject::Line || obj->getType() == LDObject::CndLine) |
540 if (obj->getType() == LDObject::Line || obj->getType() == LDObject::CndLine) |
527 col = edgecolor; |
541 col = edgecolor; |
528 |
542 |
529 obj->setColor (col); |
543 obj->setColor (col); |
530 g_win->R()->compileObject (obj); |
544 g_win->R()->compileObject (obj); |
531 num++; |
545 num++; |
532 } |
546 } |
533 |
547 |
534 log (ForgeWindow::tr ("%1 objects uncolored"), num); |
548 log (ForgeWindow::tr ("%1 objects uncolored"), num); |
535 g_win->refresh(); |
549 g_win->refresh(); |
536 } |
550 } |
537 |
551 |
538 // ============================================================================= |
552 // ============================================================================= |
539 // ----------------------------------------------------------------------------- |
553 // ----------------------------------------------------------------------------- |
540 DEFINE_ACTION (ReplaceCoords, CTRL (R)) { |
554 DEFINE_ACTION (ReplaceCoords, CTRL (R)) |
541 QDialog* dlg = new QDialog (g_win); |
555 { QDialog* dlg = new QDialog (g_win); |
542 Ui::ReplaceCoordsUI ui; |
556 Ui::ReplaceCoordsUI ui; |
543 ui.setupUi (dlg); |
557 ui.setupUi (dlg); |
544 |
558 |
545 if (!dlg->exec()) |
559 if (!dlg->exec()) |
546 return; |
560 return; |
547 |
561 |
548 const double search = ui.search->value(), |
562 const double search = ui.search->value(), |
549 replacement = ui.replacement->value(); |
563 replacement = ui.replacement->value(); |
550 const bool any = ui.any->isChecked(), |
564 const bool any = ui.any->isChecked(), |
551 rel = ui.relative->isChecked(); |
565 rel = ui.relative->isChecked(); |
552 |
566 |
553 List<Axis> sel; |
567 List<Axis> sel; |
554 int num = 0; |
568 int num = 0; |
555 |
569 |
|
570 if (ui.x->isChecked()) sel << X; |
|
571 |
|
572 if (ui.y->isChecked()) sel << Y; |
|
573 |
|
574 if (ui.z->isChecked()) sel << Z; |
|
575 |
|
576 for (LDObject* obj : g_win->sel()) |
|
577 for (short i = 0; i < obj->vertices(); ++i) |
|
578 { vertex v = obj->getVertex (i); |
|
579 |
|
580 for (Axis ax : sel) |
|
581 { double& coord = v[ax]; |
|
582 |
|
583 if (any || coord == search) |
|
584 { if (!rel) |
|
585 coord = 0; |
|
586 |
|
587 coord += replacement; |
|
588 num++; |
|
589 } |
|
590 } |
|
591 |
|
592 obj->setVertex (i, v); |
|
593 g_win->R()->compileObject (obj); |
|
594 } |
|
595 |
|
596 log (ForgeWindow::tr ("Altered %1 values"), num); |
|
597 g_win->refresh(); |
|
598 } |
|
599 |
|
600 // ============================================================================= |
|
601 // ----------------------------------------------------------------------------- |
|
602 DEFINE_ACTION (Flip, CTRL_SHIFT (F)) |
|
603 { QDialog* dlg = new QDialog; |
|
604 Ui::FlipUI ui; |
|
605 ui.setupUi (dlg); |
|
606 |
|
607 if (!dlg->exec()) |
|
608 return; |
|
609 |
|
610 List<Axis> sel; |
|
611 |
556 if (ui.x->isChecked()) sel << X; |
612 if (ui.x->isChecked()) sel << X; |
557 if (ui.y->isChecked()) sel << Y; |
613 if (ui.y->isChecked()) sel << Y; |
558 if (ui.z->isChecked()) sel << Z; |
614 if (ui.z->isChecked()) sel << Z; |
559 |
615 |
560 for (LDObject* obj : g_win->sel()) |
616 for (LDObject* obj : g_win->sel()) |
561 for (short i = 0; i < obj->vertices(); ++i) { |
617 for (short i = 0; i < obj->vertices(); ++i) |
562 vertex v = obj->getVertex (i); |
618 { vertex v = obj->getVertex (i); |
563 |
619 |
564 for (Axis ax : sel) { |
|
565 double& coord = v[ax]; |
|
566 |
|
567 if (any || coord == search) { |
|
568 if (!rel) |
|
569 coord = 0; |
|
570 |
|
571 coord += replacement; |
|
572 num++; |
|
573 } |
|
574 } |
|
575 |
|
576 obj->setVertex (i, v); |
|
577 g_win->R()->compileObject (obj); |
|
578 } |
|
579 |
|
580 log (ForgeWindow::tr ("Altered %1 values"), num); |
|
581 g_win->refresh(); |
|
582 } |
|
583 |
|
584 // ============================================================================= |
|
585 // ----------------------------------------------------------------------------- |
|
586 DEFINE_ACTION (Flip, CTRL_SHIFT (F)) { |
|
587 QDialog* dlg = new QDialog; |
|
588 Ui::FlipUI ui; |
|
589 ui.setupUi (dlg); |
|
590 |
|
591 if (!dlg->exec()) |
|
592 return; |
|
593 |
|
594 List<Axis> sel; |
|
595 if (ui.x->isChecked()) sel << X; |
|
596 if (ui.y->isChecked()) sel << Y; |
|
597 if (ui.z->isChecked()) sel << Z; |
|
598 |
|
599 for (LDObject* obj : g_win->sel()) |
|
600 for (short i = 0; i < obj->vertices(); ++i) { |
|
601 vertex v = obj->getVertex (i); |
|
602 |
|
603 for (Axis ax : sel) |
620 for (Axis ax : sel) |
604 v[ax] *= -1; |
621 v[ax] *= -1; |
605 |
622 |
606 obj->setVertex (i, v); |
623 obj->setVertex (i, v); |
607 g_win->R()->compileObject (obj); |
624 g_win->R()->compileObject (obj); |
608 } |
625 } |
609 |
626 |
610 g_win->refresh(); |
627 g_win->refresh(); |
611 } |
628 } |
612 |
629 |
613 // ============================================================================= |
630 // ============================================================================= |
614 // ----------------------------------------------------------------------------- |
631 // ----------------------------------------------------------------------------- |
615 DEFINE_ACTION (Demote, 0) { |
632 DEFINE_ACTION (Demote, 0) |
616 List<LDObject*> sel = g_win->sel(); |
633 { List<LDObject*> sel = g_win->sel(); |
617 int num = 0; |
634 int num = 0; |
618 |
635 |
619 for (LDObject* obj : sel) { |
636 for (LDObject* obj : sel) |
620 if (obj->getType() != LDObject::CndLine) |
637 { if (obj->getType() != LDObject::CndLine) |
621 continue; |
638 continue; |
622 |
639 |
623 LDLine* repl = static_cast<LDCndLine*> (obj)->demote(); |
640 LDLine* repl = static_cast<LDCndLine*> (obj)->demote(); |
624 g_win->R()->compileObject (repl); |
641 g_win->R()->compileObject (repl); |
625 ++num; |
642 ++num; |
626 } |
643 } |
627 |
644 |
628 log (ForgeWindow::tr ("Demoted %1 conditional lines"), num); |
645 log (ForgeWindow::tr ("Demoted %1 conditional lines"), num); |
629 g_win->refresh(); |
646 g_win->refresh(); |
630 } |
647 } |
631 |
648 |
632 // ============================================================================= |
649 // ============================================================================= |
633 // ----------------------------------------------------------------------------- |
650 // ----------------------------------------------------------------------------- |
634 static bool isColorUsed (short colnum) { |
651 static bool isColorUsed (short colnum) |
635 for (LDObject* obj : LDFile::current()->objects()) |
652 { for (LDObject* obj : LDFile::current()->objects()) |
636 if (obj->isColored() && obj->color() == colnum) |
653 if (obj->isColored() && obj->color() == colnum) |
637 return true; |
654 return true; |
638 |
655 |
639 return false; |
656 return false; |
640 } |
657 } |
641 |
658 |
642 // ============================================================================= |
659 // ============================================================================= |
643 // ----------------------------------------------------------------------------- |
660 // ----------------------------------------------------------------------------- |
644 DEFINE_ACTION (Autocolor, 0) { |
661 DEFINE_ACTION (Autocolor, 0) |
645 short colnum = 0; |
662 { short colnum = 0; |
646 |
663 |
647 while (colnum < MAX_COLORS && (getColor (colnum) == null || isColorUsed (colnum))) |
664 while (colnum < MAX_COLORS && (getColor (colnum) == null || isColorUsed (colnum))) |
648 colnum++; |
665 colnum++; |
649 |
666 |
650 if (colnum >= MAX_COLORS) { |
667 if (colnum >= MAX_COLORS) |
651 log (ForgeWindow::tr ("Cannot auto-color: all colors are in use!")); |
668 { log (ForgeWindow::tr ("Cannot auto-color: all colors are in use!")); |
652 return; |
669 return; |
653 } |
670 } |
654 |
671 |
655 for (LDObject* obj : g_win->sel()) { |
672 for (LDObject* obj : g_win->sel()) |
656 if (obj->isColored() == false) |
673 { if (obj->isColored() == false) |
657 continue; |
674 continue; |
658 |
675 |
659 obj->setColor (colnum); |
676 obj->setColor (colnum); |
660 g_win->R()->compileObject (obj); |
677 g_win->R()->compileObject (obj); |
661 } |
678 } |
662 |
679 |
663 log (ForgeWindow::tr ("Auto-colored: new color is [%1] %2"), colnum, getColor (colnum)->name); |
680 log (ForgeWindow::tr ("Auto-colored: new color is [%1] %2"), colnum, getColor (colnum)->name); |
664 g_win->refresh(); |
681 g_win->refresh(); |
665 } |
682 } |
666 |
683 |
667 // ============================================================================= |
684 // ============================================================================= |
668 // ----------------------------------------------------------------------------- |
685 // ----------------------------------------------------------------------------- |
669 DEFINE_ACTION (AddHistoryLine, 0) { |
686 DEFINE_ACTION (AddHistoryLine, 0) |
670 LDObject* obj; |
687 { LDObject* obj; |
671 bool ishistory = false, |
688 bool ishistory = false, |
672 prevIsHistory = false; |
689 prevIsHistory = false; |
673 |
690 |
674 QDialog* dlg = new QDialog; |
691 QDialog* dlg = new QDialog; |
675 Ui_AddHistoryLine* ui = new Ui_AddHistoryLine; |
692 Ui_AddHistoryLine* ui = new Ui_AddHistoryLine; |
676 ui->setupUi (dlg); |
693 ui->setupUi (dlg); |
677 ui->m_username->setText (ld_defaultuser); |
694 ui->m_username->setText (ld_defaultuser); |
678 ui->m_date->setDate (QDate::currentDate()); |
695 ui->m_date->setDate (QDate::currentDate()); |
679 ui->m_comment->setFocus(); |
696 ui->m_comment->setFocus(); |
680 |
697 |
681 if (!dlg->exec()) |
698 if (!dlg->exec()) |
682 return; |
699 return; |
683 |
700 |
684 // Create the comment object based on input |
701 // Create the comment object based on input |
685 str commentText = fmt ("!HISTORY %1 [%2] %3", |
702 str commentText = fmt ("!HISTORY %1 [%2] %3", |
686 ui->m_date->date().toString("yyyy-MM-dd"), |
703 ui->m_date->date().toString ("yyyy-MM-dd"), |
687 ui->m_username->text(), |
704 ui->m_username->text(), |
688 ui->m_comment->text()); |
705 ui->m_comment->text()); |
689 |
706 |
690 LDComment* comm = new LDComment (commentText); |
707 LDComment* comm = new LDComment (commentText); |
691 |
708 |
692 // Find a spot to place the new comment |
709 // Find a spot to place the new comment |
693 for ( |
710 for ( |
694 obj = LDFile::current()->object (0); |
711 obj = LDFile::current()->object (0); |
695 obj && obj->next() && !obj->next()->isScemantic(); |
712 obj && obj->next() && !obj->next()->isScemantic(); |
696 obj = obj->next() |
713 obj = obj->next() |
697 ) { |
714 ) |
698 LDComment* comm = dynamic_cast<LDComment*> (obj); |
715 { LDComment* comm = dynamic_cast<LDComment*> (obj); |
|
716 |
699 if (comm && comm->text.startsWith ("!HISTORY ")) |
717 if (comm && comm->text.startsWith ("!HISTORY ")) |
700 ishistory = true; |
718 ishistory = true; |
701 |
719 |
702 if (prevIsHistory && !ishistory) { |
720 if (prevIsHistory && !ishistory) |
703 // Last line was history, this isn't, thus insert the new history |
721 { // Last line was history, this isn't, thus insert the new history |
704 // line here. |
722 // line here. |
705 break; |
723 break; |
706 } |
724 } |
707 |
725 |
708 prevIsHistory = ishistory; |
726 prevIsHistory = ishistory; |
709 } |
727 } |
710 |
728 |
711 int idx = obj ? obj->getIndex() : 0; |
729 int idx = obj ? obj->getIndex() : 0; |
712 LDFile::current()->insertObj (idx++, comm); |
730 LDFile::current()->insertObj (idx++, comm); |
713 |
731 |
714 // If we're adding a history line right before a scemantic object, pad it |
732 // If we're adding a history line right before a scemantic object, pad it |
715 // an empty line |
733 // an empty line |
716 if (obj && obj->next() && obj->next()->isScemantic()) |
734 if (obj && obj->next() && obj->next()->isScemantic()) |
717 LDFile::current()->insertObj (idx, new LDEmpty); |
735 LDFile::current()->insertObj (idx, new LDEmpty); |
718 |
736 |
719 g_win->buildObjList(); |
737 g_win->buildObjList(); |
720 delete ui; |
738 delete ui; |
721 } |
739 } |