]> Shamusworld >> Repos - architektonas/blob - src/utils.cpp
98902d7a80a439de0b39a6a0613e963dde30d1aa
[architektonas] / src / utils.cpp
1 // utils.cpp: Stuff that's useful to have kicking around, in one spot
2 //
3 // Part of the Architektonas Project
4 // (C) 2020 Underground Software
5 // See the README and GPLv3 files for licensing and warranty information
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 //
9 // Who  When        What
10 // ---  ----------  ------------------------------------------------------------
11 // JLH  05/01/2015  Created this file
12 //
13
14 #include "utils.h"
15 #include <string.h>             // For memcpy()
16 #include "geometry.h"
17
18
19 //
20 // Copy objects in one vector to another, creating copies and placing them in
21 // the other vector. Clearing & etc. of vectors is responsibility of the caller!
22 //
23 void CopyObjects(std::vector<void *> & from, std::vector<void *> & to)
24 {
25         for(std::vector<void *>::iterator i=from.begin(); i!=from.end(); i++)
26         {
27                 Object * obj = (Object *)(*i);
28                 Object * newObject = CopyObject(obj);
29                 to.push_back(newObject);
30         }
31 }
32
33
34 //
35 // Create a copy of the passed in object.
36 //
37 Object * CopyObject(Object * obj)
38 {
39         void * newObject = NULL;
40
41         switch (obj->type)
42         {
43         case OTLine:
44                 newObject = new Line();
45                 memcpy(newObject, obj, sizeof(Line));
46                 break;
47         case OTCircle:
48                 newObject = new Circle();
49                 memcpy(newObject, obj, sizeof(Circle));
50                 break;
51         case OTEllipse:
52                 newObject = new Ellipse();
53                 memcpy(newObject, obj, sizeof(Ellipse));
54                 break;
55         case OTArc:
56                 newObject = new Arc();
57                 memcpy(newObject, obj, sizeof(Arc));
58                 break;
59         case OTDimension:
60                 newObject = new Dimension();
61                 memcpy(newObject, obj, sizeof(Dimension));
62                 break;
63 #if 0
64         case OTSpline:
65                 newObject = new Spline();
66                 memcpy(newObject, obj, sizeof(Spline));
67                 break;
68 #endif
69         case OTText:
70                 newObject = new Text();
71                 memcpy(newObject, obj, sizeof(Text));
72                 ((Text *)newObject)->s = ((Text *)obj)->s;
73                 break;
74         case OTContainer:
75                 newObject = new Container();
76 //this won't work...
77 //              memcpy(newObject, obj, sizeof(Line));
78                 ((Container *)newObject)->p[0] = obj->p[0];
79                 ((Container *)newObject)->p[1] = obj->p[1];
80                 CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects);
81                 break;
82         default:
83                 break;
84         }
85
86         // Fix objectID
87         if (newObject && (((Object *)newObject)->type != OTContainer))
88                 ((Object *)newObject)->id = Global::objectID++;
89
90         return (Object *)newObject;
91 }
92
93
94 void MoveSelectedObjectsTo(std::vector<void *> & dest, std::vector<void *> & from)
95 {
96         std::vector<void *>::iterator i = from.begin();
97
98         while (i != from.end())
99         {
100                 Object * obj = (Object *)(*i);
101
102                 if (obj->selected)
103                 {
104                         dest.push_back(*i);
105                         from.erase(i);
106                 }
107                 else
108                         i++;
109         }
110 }
111
112
113 //hmm, this won't work, as these are just pointers...
114 //[should work now]
115 void CopySelectedObjectsTo(std::vector<void *> & dest, std::vector<void *> & from)
116 {
117         for(std::vector<void *>::iterator i=from.begin(); i!=from.end(); i++)
118         {
119                 Object * obj = (Object *)(*i);
120
121                 if (obj->selected)
122 //              {
123 //                      Object * newObject = CopyObject(obj);
124                         dest.push_back(CopyObject(obj));
125 //              }
126         }
127 }
128
129
130 void AddObjectsTo(std::vector<void *> & dest, std::vector<void *> & from)
131 {
132         for(std::vector<void *>::iterator i=from.begin(); i!=from.end(); i++)
133                 dest.push_back(*i);
134 }
135
136
137 void ClearSelected(std::vector<void *> & v)
138 {
139         std::vector<void *>::iterator i;
140
141         for(i=v.begin(); i!=v.end(); i++)
142                 ((Object *)(*i))->selected = false;
143 }
144
145
146 void SelectAll(std::vector<void *> & v)
147 {
148         std::vector<void *>::iterator i;
149
150         for(i=v.begin(); i!=v.end(); i++)
151                 ((Object *)(*i))->selected = true;
152 }
153
154
155 //
156 // Recursively go down thru the Container's vectors, deleting all the objects
157 // contained therein.  Once that is done, the main Container can be deleted.
158 // We don't have to worry about the underlying std::vectors, as they have their
159 // own destructors--plus they don't take ownership of objects, which is why we
160 // have to keep track of that stuff ourselves.  :-P  Believe it or not, this is
161 // a Good Thing(TM).  ;-)
162 //
163 void DeleteContents(std::vector<void *> & v)
164 {
165         std::vector<void *>::iterator i;
166
167         for(i=v.begin(); i!=v.end(); i++)
168         {
169                 Object * obj = (Object *)(*i);
170
171                 if (obj->type == OTContainer)
172                         DeleteContents(((Container *)obj)->objects);
173
174                 delete obj;
175         }
176
177         v.clear();
178 }
179
180
181 void DeleteSelectedObjects(std::vector<void *> & v)
182 {
183         std::vector<void *>::iterator i = v.begin();
184
185         while (i != v.end())
186         {
187                 Object * obj = (Object *)(*i);
188
189                 if (obj->selected)
190                 {
191                         delete obj;
192                         v.erase(i);
193                 }
194                 else
195                         i++;
196         }
197 }
198
199
200 //
201 // This is used to remove selected objects from one container in order to move
202 // them to a different container.
203 //
204 void RemoveSelectedObjects(std::vector<void *> & v)
205 {
206         std::vector<void *>::iterator i = v.begin();
207
208         while (i != v.end())
209         {
210                 Object * obj = (Object *)(*i);
211
212                 if (obj->selected)
213                         v.erase(i);
214                 else
215                         i++;
216         }
217 }
218
219
220 void SavePointsFrom(std::vector<void *> & v, std::vector<Object> & save)
221 {
222         save.clear();
223         Object o;
224
225         for(std::vector<void *>::iterator i=v.begin(); i!=v.end(); i++)
226         {
227                 memcpy(&o, (Object *)(*i), sizeof(Object));
228                 save.push_back(o);
229         }
230 }
231
232
233 void RestorePointsTo(std::vector<void *> & v, std::vector<Object> & s)
234 {
235         std::vector<Object>::iterator i = s.begin();
236         std::vector<void *>::iterator j = v.begin();
237
238         for(; i!=s.end(); i++, j++)
239         {
240                 Object * obj2 = (Object *)(*j);
241                 obj2->p[0] = (*i).p[0];
242                 obj2->p[1] = (*i).p[1];
243                 obj2->angle[0] = (*i).angle[0];
244                 obj2->angle[1] = (*i).angle[1];
245 //we don't do this because we want to keep selected & friends from changing
246 //              memcpy(obj2, *j, sizeof(Object));
247         }
248 }
249
250
251 void RestorePointsTo(std::vector<void *> & v, std::vector<void *> & s)
252 {
253         std::vector<void *>::iterator i = s.begin();
254         std::vector<void *>::iterator j = v.begin();
255
256         for(; i!=s.end(); i++, j++)
257         {
258                 Object * objS = (Object *)(*i);
259                 Object * objV = (Object *)(*j);
260
261                 if (objV->type == OTContainer)
262                 {
263                         RestorePointsTo(((Container *)objV)->objects, ((Container *)objS)->objects);
264                         return;
265                 }
266
267                 objV->p[0] = objS->p[0];
268                 objV->p[1] = objS->p[1];
269                 objV->angle[0] = objS->angle[0];
270                 objV->angle[1] = objS->angle[1];
271 //we don't do this because we want to keep selected & friends from changing
272 //              memcpy(obj2, *j, sizeof(Object));
273         }
274 }
275
276
277 void TranslateObject(Object * obj, Point delta)
278 {
279         if (obj->type == OTContainer)
280         {
281                 Container * c = (Container *)obj;
282                 std::vector<void *>::iterator i;
283
284                 for(i=c->objects.begin(); i!=c->objects.end(); i++)
285                         TranslateObject((Object *)*i, delta);
286         }
287 //      else
288 //      {
289                 obj->p[0] += delta;
290                 obj->p[1] += delta;
291 //      }
292 }
293
294
295 /*
296 So we need to make it so that we pick the container's point clicked on, and translate all the other parts *not* clicked on.
297 */
298 void TranslateContainer(Container * c, Point point, Point delta)
299 {
300         if (c->clicked == NULL)
301         {
302 //              TranslateObject((Object *)c, delta);
303                 return;
304         }
305
306 static int i=0;
307 printf("TranslateContainer: boop (%i)\n", i++);
308         Point clickedPoint;
309
310         switch (c->clicked->type)
311         {
312         case OTLine:
313                 if (c->clicked->hitPoint[0])
314                         clickedPoint = c->clicked->p[0];
315                 else if (c->clicked->hitPoint[1])
316                         clickedPoint = c->clicked->p[1];
317                 else if (c->clicked->hitObject)
318                         clickedPoint = Geometry::Midpoint((Line *)(c->clicked));
319
320                 break;
321
322         case OTCircle:
323                 if (c->clicked->hitPoint[0])
324                         clickedPoint = c->clicked->p[0];
325                 else if (c->clicked->hitObject)
326                         clickedPoint = point;
327
328                 break;
329
330         case OTArc:
331                 break;
332
333         case OTDimension:
334                 break;
335
336         case OTText:
337                 break;
338         }
339
340         Point clickedDelta = point - clickedPoint;
341         TranslateObject((Object *)c, clickedDelta);
342 }
343
344
345 void TranslateObjects(std::vector<void *> & v, Point delta)
346 {
347 #if 0
348         if (obj->type == OTContainer)
349         {
350                 Container * c = (Container *)obj;
351                 std::vector<void *>::iterator i;
352
353                 for(i=c->objects.begin(); i!=c->objects.end(); i++)
354                         TranslateObject((Object *)*i, delta);
355         }
356         else
357         {
358                 obj->p[0] += delta;
359                 obj->p[1] += delta;
360         }
361 #endif
362         // Handle containters too???
363         std::vector<void *>::iterator i;
364
365         for(i=v.begin(); i!=v.end(); i++)
366         {
367                 Object * obj = (Object *)(*i);
368                 obj->p[0] += delta;
369                 obj->p[1] += delta;
370         }
371 }
372
373
374 std::vector<void *> Flatten(Container * src)
375 {
376         std::vector<void *> flat;
377         std::vector<void *>::iterator i;
378
379         for(i=src->objects.begin(); i!=src->objects.end(); i++)
380         {
381                 flat.push_back(*i);
382                 Object * obj = (Object *)(*i);
383
384                 // Recursively add objects to the flat vector, if necessary
385                 if (obj->type == OTContainer)
386                 {
387                         std::vector<void *> sub = Flatten((Container *)obj);
388                         flat.insert(flat.end(), sub.begin(), sub.end());
389                 }
390         }
391
392         return flat;
393 }
394