X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Futils.cpp;h=cd05ba735e95f30ac96aacf56f205e6548840a79;hb=10cf4c797bed05831e976068b7504908279dc997;hp=02d6b20ef9c6fe977aa9efe5de0a4f5e6e70baa7;hpb=e78daf62eb771ee29a59035d16cf63c1e6ebe144;p=architektonas diff --git a/src/utils.cpp b/src/utils.cpp index 02d6b20..cd05ba7 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,7 +1,8 @@ +// // utils.cpp: Stuff that's useful to have kicking around, in one spot // // Part of the Architektonas Project -// (C) 2015 Underground Software +// (C) 2020 Underground Software // See the README and GPLv3 files for licensing and warranty information // // JLH = James Hammons @@ -12,18 +13,17 @@ // #include "utils.h" +#include #include // For memcpy() - +#include "geometry.h" // // Copy objects in one vector to another, creating copies and placing them in // the other vector. Clearing & etc. of vectors is responsibility of the caller! // -void CopyObjects(std::vector & from, std::vector & to) +void CopyObjects(VPVector & from, VPVector & to) { - std::vector::iterator i; - - for(i=from.begin(); i!=from.end(); i++) + for(VPVectorIter i=from.begin(); i!=from.end(); i++) { Object * obj = (Object *)(*i); Object * newObject = CopyObject(obj); @@ -31,51 +31,69 @@ void CopyObjects(std::vector & from, std::vector & to) } } +VPVector CopyObjects(VPVector & src) +{ + VPVector copy; + + for(VPVectorIter i=src.begin(); i!=src.end(); i++) + { + Object * newObject = CopyObject2((Object *)(*i)); + copy.push_back(newObject); + } + + return copy; +} // // Create a copy of the passed in object. // Object * CopyObject(Object * obj) { - Object * newObject = NULL; + void * newObject = NULL; switch (obj->type) { case OTLine: - newObject = (Object *)new Line(); + newObject = new Line(); memcpy(newObject, obj, sizeof(Line)); break; case OTCircle: - newObject = (Object *)new Circle(); + newObject = new Circle(); memcpy(newObject, obj, sizeof(Circle)); break; case OTEllipse: - newObject = (Object *)new Ellipse(); + newObject = new Ellipse(); memcpy(newObject, obj, sizeof(Ellipse)); break; case OTArc: - newObject = (Object *)new Arc(); + newObject = new Arc(); memcpy(newObject, obj, sizeof(Arc)); break; case OTDimension: - newObject = (Object *)new Dimension(); + newObject = new Dimension(); memcpy(newObject, obj, sizeof(Dimension)); break; -#if 0 + case OTPolyline: + newObject = new Polyline(); + memcpy(newObject, obj, sizeof(Polyline)); + ((Polyline *)newObject)->points = ((Polyline *)obj)->points; + break; case OTSpline: - newObject = (Object *)new Spline(); + newObject = new Spline(); memcpy(newObject, obj, sizeof(Spline)); break; -#endif case OTText: - newObject = (Object *)new Text(); + newObject = new Text(); memcpy(newObject, obj, sizeof(Text)); ((Text *)newObject)->s = ((Text *)obj)->s; break; case OTContainer: - newObject = (Object *)new Container(); + newObject = new Container(); //this won't work... // memcpy(newObject, obj, sizeof(Line)); + ((Container *)newObject)->p[0] = obj->p[0]; + ((Container *)newObject)->p[1] = obj->p[1]; + ((Container *)newObject)->layer = obj->layer; CopyObjects(((Container *)obj)->objects, ((Container *)newObject)->objects); break; default: @@ -83,16 +101,83 @@ Object * CopyObject(Object * obj) } // Fix objectID - if (newObject && (newObject->type != OTContainer)) - newObject->id = Global::objectID; + if (newObject && (((Object *)newObject)->type != OTContainer)) + ((Object *)newObject)->id = Global::objectID++; - return newObject; + return (Object *)newObject; } +// +// Create a copy of the passed in object. This version calls the second +// version of CopyObjects() (with one parameter and a vector return value). +// +Object * CopyObject2(Object * obj) +{ + void * newObject = NULL; + + switch (obj->type) + { + case OTLine: + newObject = new Line(); + memcpy(newObject, obj, sizeof(Line)); + break; + + case OTCircle: + newObject = new Circle(); + memcpy(newObject, obj, sizeof(Circle)); + break; -void MoveSelectedObjectsTo(std::vector & dest, std::vector & from) + case OTEllipse: + newObject = new Ellipse(); + memcpy(newObject, obj, sizeof(Ellipse)); + break; + + case OTArc: + newObject = new Arc(); + memcpy(newObject, obj, sizeof(Arc)); + break; + + case OTDimension: + newObject = new Dimension(); + memcpy(newObject, obj, sizeof(Dimension)); + break; + + case OTPolyline: + newObject = new Polyline(); + memcpy(newObject, obj, sizeof(Polyline)); + ((Polyline *)newObject)->points = ((Polyline *)obj)->points; + break; + + case OTSpline: + newObject = new Spline(); + memcpy(newObject, obj, sizeof(Spline)); + break; + + case OTText: + newObject = new Text(); + memcpy(newObject, obj, sizeof(Text)); + ((Text *)newObject)->s = ((Text *)obj)->s; + break; + + case OTContainer: + newObject = new Container(); + ((Container *)newObject)->p[0] = obj->p[0]; + ((Container *)newObject)->p[1] = obj->p[1]; + ((Container *)newObject)->layer = obj->layer; + ((Container *)newObject)->objects = CopyObjects(((Container *)obj)->objects); + break; + } + + // Fix objectID + if (newObject && (((Object *)newObject)->type != OTContainer)) + ((Object *)newObject)->id = Global::objectID++; + + return (Object *)newObject; +} + +void MoveSelectedObjectsTo(VPVector & dest, VPVector & from) { - std::vector::iterator i = from.begin(); + VPVectorIter i = from.begin(); while (i != from.end()) { @@ -108,45 +193,91 @@ void MoveSelectedObjectsTo(std::vector & dest, std::vector & fro } } - -void AddObjectsTo(std::vector & dest, std::vector & from) +VPVector MoveSelectedObjectsFrom(VPVector & from) { - for(std::vector::iterator i=from.begin(); i!=from.end(); i++) - dest.push_back(*i); -} + VPVector objects; + VPVectorIter i = from.begin(); + while (i != from.end()) + { + Object * obj = (Object *)(*i); + + if (obj->selected) + { + objects.push_back(*i); + from.erase(i); + } + else + i++; + } + + return objects; +} -void ClearSelected(std::vector & v) +//hmm, this won't work, as these are just pointers... +//[should work now] +void CopySelectedObjectsTo(VPVector & dest, VPVector & from) { - std::vector::iterator i; + for(VPVectorIter i=from.begin(); i!=from.end(); i++) + { + Object * obj = (Object *)(*i); - for(i=v.begin(); i!=v.end(); i++) - ((Object *)(*i))->selected = false; + if (obj->selected) + dest.push_back(CopyObject2(obj)); + } } +VPVector CopySelectedObjects(VPVector & src) +{ + VPVector copy; + + for(VPVectorIter i=src.begin(); i!=src.end(); i++) + { + Object * obj = (Object *)(*i); + + if (obj->selected) + copy.push_back(CopyObject2(obj)); + } -void SelectAll(std::vector & v) + return copy; +} + +void AddObjectsTo(VPVector & dest, VPVector & from) { - std::vector::iterator i; + for(VPVectorIter i=from.begin(); i!=from.end(); i++) + dest.push_back(*i); +} - for(i=v.begin(); i!=v.end(); i++) - ((Object *)(*i))->selected = true; +void ClearSelected(VPVector & v) +{ + for(VPVectorIter i=v.begin(); i!=v.end(); i++) + ((Object *)(*i))->selected = false; } +// +// Select all *visible* objects. If an object's layer is invisible, skip it. +// +void SelectAll(VPVector & v) +{ + for(VPVectorIter i=v.begin(); i!=v.end(); i++) + { + Object * obj = (Object *)(*i); + bool visible = !Global::layerHidden[obj->layer]; + obj->selected = visible; + } +} // // Recursively go down thru the Container's vectors, deleting all the objects -// contained therein. Once that is done, the main Container can be deleted. We -// don't have to worry about the underlying std::vectors, as they have their +// contained therein. Once that is done, the main Container can be deleted. +// We don't have to worry about the underlying std::vectors, as they have their // own destructors--plus they don't take ownership of objects, which is why we -// have to keep track of that stuff ourselves. :-P Believe it or not, this is a -// Good Thing(TM). ;-) +// have to keep track of that stuff ourselves. :-P Believe it or not, this is +// a Good Thing(TM). ;-) // -void DeleteContents(std::vector & v) +void DeleteContents(VPVector & v) { - std::vector::iterator i; - - for(i=v.begin(); i!=v.end(); i++) + for(VPVectorIter i=v.begin(); i!=v.end(); i++) { Object * obj = (Object *)(*i); @@ -155,11 +286,13 @@ void DeleteContents(std::vector & v) delete obj; } + + v.clear(); } -void DeleteSelectedObjects(std::vector & v) +void DeleteSelectedObjects(VPVector & v) { - std::vector::iterator i = v.begin(); + VPVectorIter i = v.begin(); while (i != v.end()) { @@ -175,14 +308,13 @@ void DeleteSelectedObjects(std::vector & v) } } - // // This is used to remove selected objects from one container in order to move // them to a different container. // -void RemoveSelectedObjects(std::vector & v) +void RemoveSelectedObjects(VPVector & v) { - std::vector::iterator i = v.begin(); + VPVectorIter i = v.begin(); while (i != v.end()) { @@ -195,26 +327,43 @@ void RemoveSelectedObjects(std::vector & v) } } +// +// This is used to remove hovered objects from one container in order to delete +// them from the same container. +// +void RemoveHoveredObjects(VPVector & v) +{ + VPVectorIter i = v.begin(); + + while (i != v.end()) + { + Object * obj = (Object *)(*i); + + if (obj->hovered) + v.erase(i); + else + i++; + } +} -void SavePointsFrom(std::vector & v, std::vector & save) +void SavePointsFrom(VPVector & v, std::vector & save) { save.clear(); Object o; - for(std::vector::iterator i=v.begin(); i!=v.end(); i++) + for(VPVectorIter i=v.begin(); i!=v.end(); i++) { - memcpy(&o, (*i), sizeof(Object)); + memcpy(&o, (Object *)(*i), sizeof(Object)); save.push_back(o); } } - -void RestorePointsTo(std::vector & v, std::vector & s) +void RestorePointsTo(VPVector & v, std::vector & s) { - std::vector::iterator i = s.begin(); - std::vector::iterator j = v.begin(); + std::vector::iterator i; + VPVectorIter j; - for(; i!=s.end(); i++, j++) + for(i=s.begin(), j=v.begin(); i!=s.end(); i++, j++) { Object * obj2 = (Object *)(*j); obj2->p[0] = (*i).p[0]; @@ -226,22 +375,177 @@ void RestorePointsTo(std::vector & v, std::vector & s) } } +void RestorePointsTo(VPVector & v, VPVector & s) +{ + for(VPVectorIter i=s.begin(), j=v.begin(); i!=s.end(); i++, j++) + { + Object * objS = (Object *)(*i); + Object * objV = (Object *)(*j); + + if (objV->type == OTContainer) + { + RestorePointsTo(((Container *)objV)->objects, ((Container *)objS)->objects); + return; + } + objV->p[0] = objS->p[0]; + objV->p[1] = objS->p[1]; + objV->angle[0] = objS->angle[0]; + objV->angle[1] = objS->angle[1]; +//we don't do this because we want to keep selected & friends from changing +// memcpy(obj2, *j, sizeof(Object)); + } +} + +// +// Translate a single object; it it's a Container, translate all its contents, +// including subcontainers. +// void TranslateObject(Object * obj, Point delta) { if (obj->type == OTContainer) { Container * c = (Container *)obj; - std::vector::iterator i; - for(i=c->objects.begin(); i!=c->objects.end(); i++) + for(VPVectorIter i=c->objects.begin(); i!=c->objects.end(); i++) TranslateObject((Object *)*i, delta); } - else + else if (obj->type == OTPolyline) + ((Polyline *)obj)->Translate(delta); + + obj->p[0] += delta; + obj->p[1] += delta; +} + +/* +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. +*/ +void TranslateContainer(Container * c, Point point, Point delta) +{ + if (c->clicked == NULL) +// { +// TranslateObject((Object *)c, delta); + return; +// } + +//static int i=0; +//printf("TranslateContainer: boop (%i)\n", i++); +//we can set this to "point" and it won't move... +//do it *this* way, and non-enumerated clicks will do the right thing + Point clickedPoint = point - delta; + + switch (c->clicked->type) { + case OTLine: + if (c->clicked->hitPoint[0]) + clickedPoint = c->clicked->p[0]; + else if (c->clicked->hitPoint[1]) + clickedPoint = c->clicked->p[1]; + else if (c->clicked->hitObject) +//Weirdness: some lines get a midpoint, some don't... + clickedPoint = Geometry::Midpoint((Line *)(c->clicked)); + + break; + + case OTCircle: + if (c->clicked->hitPoint[0]) + clickedPoint = c->clicked->p[0]; +// else if (c->clicked->hitObject) +// clickedPoint = point - delta; + + break; + + case OTArc: + if (c->clicked->hitPoint[0]) + clickedPoint = c->clicked->p[0]; + else if (c->clicked->hitPoint[1]) + clickedPoint = c->clicked->p[0] + (Vector(cos(c->clicked->angle[0]), sin(c->clicked->angle[0])) * c->clicked->radius[0]); + else if (c->clicked->hitPoint[2]) + 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]); +// else if (c->clicked->hitObject) +// clickedPoint = point - delta; + + break; + + case OTDimension: + break; + + case OTText: + break; + } + + Point clickedDelta = point - clickedPoint; + TranslateObject((Object *)c, clickedDelta); +} + +// +// Translate all objects in the passed in vector, including Containers and all +// the objects they contain. +// +void TranslateObjects(VPVector & v, Point delta) +{ + for(VPVectorIter i=v.begin(); i!=v.end(); i++) + { + Object * obj = (Object *)(*i); obj->p[0] += delta; obj->p[1] += delta; + + if (obj->type == OTContainer) + { + Container * c = (Container *)obj; + TranslateObjects(c->objects, delta); + } + else if (obj->type == OTPolyline) + { + ((Polyline *)obj)->Translate(delta); + } + } +} + +// +// This does not *copy* the objects, it simply flattens out the pointers in the +// Container and all sub-Containers. +// +VPVector Flatten(Container * src) +{ + VPVector flat; + + for(VPVectorIter i=src->objects.begin(); i!=src->objects.end(); i++) + { + flat.push_back(*i); + Object * obj = (Object *)(*i); + + // Recursively add objects to the flat vector, if necessary + if (obj->type == OTContainer) + { + VPVector sub = Flatten((Container *)obj); + flat.insert(flat.end(), sub.begin(), sub.end()); + } } + + return flat; } +// +// This does not *copy* the objects, it simply flattens out the pointers in the +// vector and all sub-Containers in the vector. +// +VPVector Flatten(VPVector src) +{ + VPVector flat; + + for(VPVectorIter i=src.begin(); i!=src.end(); i++) + { + flat.push_back(*i); + Object * obj = (Object *)(*i); + // Recursively add objects to the flat vector, if necessary + if (obj->type == OTContainer) + { + VPVector sub = Flatten(((Container *)obj)->objects); + flat.insert(flat.end(), sub.begin(), sub.end()); + } + } + + return flat; +}