2 // utils.cpp: Stuff that's useful to have kicking around, in one spot
4 // Part of the Architektonas Project
5 // (C) 2020 Underground Software
6 // See the README and GPLv3 files for licensing and warranty information
8 // JLH = James Hammons <jlhamm@acm.org>
11 // --- ---------- ------------------------------------------------------------
12 // JLH 05/01/2015 Created this file
17 #include <string.h> // For memcpy()
21 // Copy objects in one vector to another, creating copies and placing them in
22 // the other vector. Clearing & etc. of vectors is responsibility of the caller!
24 void CopyObjects(VPVector & from, VPVector & to)
26 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
28 Object * obj = (Object *)(*i);
29 Object * newObject = CopyObject(obj);
30 to.push_back(newObject);
34 VPVector CopyObjects(VPVector & src)
38 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
40 Object * newObject = CopyObject2((Object *)(*i));
41 copy.push_back(newObject);
48 // Create a copy of the passed in object.
50 Object * CopyObject(Object * obj)
52 void * newObject = NULL;
57 newObject = new Line();
58 memcpy(newObject, obj, sizeof(Line));
61 newObject = new Circle();
62 memcpy(newObject, obj, sizeof(Circle));
65 newObject = new Ellipse();
66 memcpy(newObject, obj, sizeof(Ellipse));
69 newObject = new Arc();
70 memcpy(newObject, obj, sizeof(Arc));
73 newObject = new Dimension();
74 memcpy(newObject, obj, sizeof(Dimension));
77 newObject = new Spline();
78 memcpy(newObject, obj, sizeof(Spline));
81 newObject = new Text();
82 memcpy(newObject, obj, sizeof(Text));
83 ((Text *)newObject)->s = ((Text *)obj)->s;
86 newObject = new Container();
88 // memcpy(newObject, obj, sizeof(Line));
89 ((Container *)newObject)->p[0] = obj->p[0];
90 ((Container *)newObject)->p[1] = obj->p[1];
91 ((Container *)newObject)->layer = obj->layer;
92 CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects);
99 if (newObject && (((Object *)newObject)->type != OTContainer))
100 ((Object *)newObject)->id = Global::objectID++;
102 return (Object *)newObject;
106 // Create a copy of the passed in object. This version calls the second
107 // version of CopyObjects() (with one parameter and a vector return value).
109 Object * CopyObject2(Object * obj)
111 void * newObject = NULL;
116 newObject = new Line();
117 memcpy(newObject, obj, sizeof(Line));
121 newObject = new Circle();
122 memcpy(newObject, obj, sizeof(Circle));
126 newObject = new Ellipse();
127 memcpy(newObject, obj, sizeof(Ellipse));
131 newObject = new Arc();
132 memcpy(newObject, obj, sizeof(Arc));
136 newObject = new Dimension();
137 memcpy(newObject, obj, sizeof(Dimension));
141 newObject = new Spline();
142 memcpy(newObject, obj, sizeof(Spline));
146 newObject = new Text();
147 memcpy(newObject, obj, sizeof(Text));
148 ((Text *)newObject)->s = ((Text *)obj)->s;
152 newObject = new Container();
153 ((Container *)newObject)->p[0] = obj->p[0];
154 ((Container *)newObject)->p[1] = obj->p[1];
155 ((Container *)newObject)->layer = obj->layer;
156 ((Container *)newObject)->objects = CopyObjects(((Container *)obj)->objects);
161 if (newObject && (((Object *)newObject)->type != OTContainer))
162 ((Object *)newObject)->id = Global::objectID++;
164 return (Object *)newObject;
167 void MoveSelectedObjectsTo(VPVector & dest, VPVector & from)
169 VPVectorIter i = from.begin();
171 while (i != from.end())
173 Object * obj = (Object *)(*i);
185 VPVector MoveSelectedObjectsFrom(VPVector & from)
188 VPVectorIter i = from.begin();
190 while (i != from.end())
192 Object * obj = (Object *)(*i);
196 objects.push_back(*i);
206 //hmm, this won't work, as these are just pointers...
208 void CopySelectedObjectsTo(VPVector & dest, VPVector & from)
210 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
212 Object * obj = (Object *)(*i);
215 dest.push_back(CopyObject2(obj));
219 VPVector CopySelectedObjects(VPVector & src)
223 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
225 Object * obj = (Object *)(*i);
228 copy.push_back(CopyObject2(obj));
234 void AddObjectsTo(VPVector & dest, VPVector & from)
236 for(VPVectorIter i=from.begin(); i!=from.end(); i++)
240 void ClearSelected(VPVector & v)
242 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
243 ((Object *)(*i))->selected = false;
247 // Select all *visible* objects. If an object's layer is invisible, skip it.
249 void SelectAll(VPVector & v)
251 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
253 Object * obj = (Object *)(*i);
254 bool visible = !Global::layerHidden[obj->layer];
255 obj->selected = visible;
260 // Recursively go down thru the Container's vectors, deleting all the objects
261 // contained therein. Once that is done, the main Container can be deleted.
262 // We don't have to worry about the underlying std::vectors, as they have their
263 // own destructors--plus they don't take ownership of objects, which is why we
264 // have to keep track of that stuff ourselves. :-P Believe it or not, this is
265 // a Good Thing(TM). ;-)
267 void DeleteContents(VPVector & v)
269 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
271 Object * obj = (Object *)(*i);
273 if (obj->type == OTContainer)
274 DeleteContents(((Container *)obj)->objects);
282 void DeleteSelectedObjects(VPVector & v)
284 VPVectorIter i = v.begin();
288 Object * obj = (Object *)(*i);
301 // This is used to remove selected objects from one container in order to move
302 // them to a different container.
304 void RemoveSelectedObjects(VPVector & v)
306 VPVectorIter i = v.begin();
310 Object * obj = (Object *)(*i);
320 // This is used to remove hovered objects from one container in order to delete
321 // them from the same container.
323 void RemoveHoveredObjects(VPVector & v)
325 VPVectorIter i = v.begin();
329 Object * obj = (Object *)(*i);
338 void SavePointsFrom(VPVector & v, std::vector<Object> & save)
343 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
345 memcpy(&o, (Object *)(*i), sizeof(Object));
350 void RestorePointsTo(VPVector & v, std::vector<Object> & s)
352 std::vector<Object>::iterator i;
355 for(i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
357 Object * obj2 = (Object *)(*j);
358 obj2->p[0] = (*i).p[0];
359 obj2->p[1] = (*i).p[1];
360 obj2->angle[0] = (*i).angle[0];
361 obj2->angle[1] = (*i).angle[1];
362 //we don't do this because we want to keep selected & friends from changing
363 // memcpy(obj2, *j, sizeof(Object));
367 void RestorePointsTo(VPVector & v, VPVector & s)
369 for(VPVectorIter i=s.begin(), j=v.begin(); i!=s.end(); i++, j++)
371 Object * objS = (Object *)(*i);
372 Object * objV = (Object *)(*j);
374 if (objV->type == OTContainer)
376 RestorePointsTo(((Container *)objV)->objects, ((Container *)objS)->objects);
380 objV->p[0] = objS->p[0];
381 objV->p[1] = objS->p[1];
382 objV->angle[0] = objS->angle[0];
383 objV->angle[1] = objS->angle[1];
384 //we don't do this because we want to keep selected & friends from changing
385 // memcpy(obj2, *j, sizeof(Object));
390 // Translate a single object; it it's a Container, translate all its contents,
391 // including subcontainers.
393 void TranslateObject(Object * obj, Point delta)
395 if (obj->type == OTContainer)
397 Container * c = (Container *)obj;
399 for(VPVectorIter i=c->objects.begin(); i!=c->objects.end(); i++)
400 TranslateObject((Object *)*i, delta);
408 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.
410 void TranslateContainer(Container * c, Point point, Point delta)
412 if (c->clicked == NULL)
414 // TranslateObject((Object *)c, delta);
419 //printf("TranslateContainer: boop (%i)\n", i++);
420 //we can set this to "point" and it won't move...
421 //do it *this* way, and non-enumerated clicks will do the right thing
422 Point clickedPoint = point - delta;
424 switch (c->clicked->type)
427 if (c->clicked->hitPoint[0])
428 clickedPoint = c->clicked->p[0];
429 else if (c->clicked->hitPoint[1])
430 clickedPoint = c->clicked->p[1];
431 else if (c->clicked->hitObject)
432 //Weirdness: some lines get a midpoint, some don't...
433 clickedPoint = Geometry::Midpoint((Line *)(c->clicked));
438 if (c->clicked->hitPoint[0])
439 clickedPoint = c->clicked->p[0];
440 // else if (c->clicked->hitObject)
441 // clickedPoint = point - delta;
446 if (c->clicked->hitPoint[0])
447 clickedPoint = c->clicked->p[0];
448 else if (c->clicked->hitPoint[1])
449 clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0]), sin(c->clicked->angle[0])) * c->clicked->radius[0]);
450 else if (c->clicked->hitPoint[2])
451 clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0] + c->clicked->angle[1]), sin(c->clicked->angle[0] + c->clicked->angle[1])) * c->clicked->radius[0]);
452 // else if (c->clicked->hitObject)
453 // clickedPoint = point - delta;
464 Point clickedDelta = point - clickedPoint;
465 TranslateObject((Object *)c, clickedDelta);
469 // Translate all objects in the passed in vector, including Containers and all
470 // the objects they contain.
472 void TranslateObjects(VPVector & v, Point delta)
474 for(VPVectorIter i=v.begin(); i!=v.end(); i++)
476 Object * obj = (Object *)(*i);
480 if (obj->type == OTContainer)
482 Container * c = (Container *)obj;
483 TranslateObjects(c->objects, delta);
489 // This does not *copy* the objects, it simply flattens out the pointers in the
490 // Container and all sub-Containers.
492 VPVector Flatten(Container * src)
496 for(VPVectorIter i=src->objects.begin(); i!=src->objects.end(); i++)
499 Object * obj = (Object *)(*i);
501 // Recursively add objects to the flat vector, if necessary
502 if (obj->type == OTContainer)
504 VPVector sub = Flatten((Container *)obj);
505 flat.insert(flat.end(), sub.begin(), sub.end());
513 // This does not *copy* the objects, it simply flattens out the pointers in the
514 // vector and all sub-Containers in the vector.
516 VPVector Flatten(VPVector src)
520 for(VPVectorIter i=src.begin(); i!=src.end(); i++)
523 Object * obj = (Object *)(*i);
525 // Recursively add objects to the flat vector, if necessary
526 if (obj->type == OTContainer)
528 VPVector sub = Flatten(((Container *)obj)->objects);
529 flat.insert(flat.end(), sub.begin(), sub.end());