src/ldtypes.cpp

changeset 665
4355e72ffd47
parent 489
0b32138fedcc
parent 528
e38d199ef9aa
--- a/src/ldtypes.cpp	Wed Sep 25 11:02:44 2013 +0300
+++ b/src/ldtypes.cpp	Wed Oct 23 12:46:10 2013 +0300
@@ -31,7 +31,7 @@
 cfg (Int, ld_defaultlicense, 0);
 
 // List of all LDObjects
-List<LDObject*> g_LDObjects;
+QList<LDObject*> g_LDObjects;
 
 // =============================================================================
 // LDObject constructors
@@ -44,13 +44,15 @@
 	qObjListEntry (null),
 	m_glinit (false)
 {
+	memset (m_coords, 0, sizeof m_coords);
+
 	// Determine ID
 	int32 id = 1; // 0 is invalid
-	
+
 	for (LDObject* obj : g_LDObjects)
 		if (obj->id() >= id)
 			id = obj->id() + 1;
-	
+
 	setID (id);
 	g_LDObjects << this;
 }
@@ -60,34 +62,34 @@
 // actually called, for a subclass-less LDObject should never come into existance.
 // These exist only to satisfy the linker.
 // -----------------------------------------------------------------------------
-LDObject::Type LDObject::getType() const {
-	return LDObject::Unidentified;
+LDObject::Type LDObject::getType() const
+{	return LDObject::Unidentified;
 }
 
-bool LDObject::hasMatrix() const {
-	return false;
+bool LDObject::hasMatrix() const
+{	return false;
 }
 
-bool LDObject::isColored() const {
-	return false;
+bool LDObject::isColored() const
+{	return false;
 }
 
-bool LDObject::isScemantic() const {
-	return false;
+bool LDObject::isScemantic() const
+{	return false;
 }
 
-str LDObject::typeName() const {
-	return "";
+str LDObject::typeName() const
+{	return "";
 }
 
-short LDObject::vertices() const {
-	return 0;
+short LDObject::vertices() const
+{	return 0;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDObject::setVertexCoord (int i, Axis ax, double value) {
-	vertex v = getVertex (i);
+void LDObject::setVertexCoord (int i, Axis ax, double value)
+{	vertex v = getVertex (i);
 	v[ax] = value;
 	setVertex (i, v);
 }
@@ -96,14 +98,14 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDComment::raw() {
-	return fmt ("0 %1", text);
+str LDComment::raw()
+{	return fmt ("0 %1", text);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDSubfile::raw() {
-	str val = fmt ("1 %1 %2 ", color(), position());
+str LDSubfile::raw()
+{	str val = fmt ("1 %1 %2 ", color(), position());
 	val += transform().stringRep();
 	val += ' ';
 	val += fileInfo()->name();
@@ -112,71 +114,71 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDLine::raw() {
-	str val = fmt ("2 %1", color());
-	
-	for (ushort i = 0; i < 2; ++i)
+str LDLine::raw()
+{	str val = fmt ("2 %1", color());
+
+	for (int i = 0; i < 2; ++i)
 		val += fmt (" %1", getVertex (i));
-	
+
 	return val;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDTriangle::raw() {
-	str val = fmt ("3 %1", color());
-	
-	for (ushort i = 0; i < 3; ++i)
+str LDTriangle::raw()
+{	str val = fmt ("3 %1", color());
+
+	for (int i = 0; i < 3; ++i)
 		val += fmt (" %1", getVertex (i));
-	
+
 	return val;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDQuad::raw() {
-	str val = fmt ("4 %1", color());
-	
-	for (ushort i = 0; i < 4; ++i)
+str LDQuad::raw()
+{	str val = fmt ("4 %1", color());
+
+	for (int i = 0; i < 4; ++i)
 		val += fmt (" %1", getVertex (i));
-	
+
 	return val;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDCndLine::raw() {
-	str val = fmt ("5 %1", color());
-	
+str LDCndLine::raw()
+{	str val = fmt ("5 %1", color());
+
 	// Add the coordinates
-	for (ushort i = 0; i < 4; ++i)
+	for (int i = 0; i < 4; ++i)
 		val += fmt (" %1", getVertex (i));
-	
+
 	return val;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDError::raw() {
-	return contents;
+str LDError::raw()
+{	return contents;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDVertex::raw() {
-	return fmt ("0 !LDFORGE VERTEX %1 %2", color(), pos);
+str LDVertex::raw()
+{	return fmt ("0 !LDFORGE VERTEX %1 %2", color(), pos);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDEmpty::raw() {
-	return "";
+str LDEmpty::raw()
+{	return "";
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-const char* LDBFC::statements[] = {
-	"CERTIFY CCW",
+const char* LDBFC::statements[] =
+{	"CERTIFY CCW",
 	"CCW",
 	"CERTIFY CW",
 	"CW",
@@ -188,14 +190,14 @@
 	"NOCLIP",
 };
 
-str LDBFC::raw() {
-	return fmt ("0 BFC %1", LDBFC::statements[type]);
+str LDBFC::raw()
+{	return fmt ("0 BFC %1", LDBFC::statements[type]);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-List<LDTriangle*> LDQuad::splitToTriangles() {
-	// Create the two triangles based on this quadrilateral:
+QList<LDTriangle*> LDQuad::splitToTriangles()
+{	// Create the two triangles based on this quadrilateral:
 	// 0---3       0---3    3
 	// |   |       |  /    /|
 	// |   |  ==>  | /    / |
@@ -203,12 +205,12 @@
 	// 1---2       1    1---2
 	LDTriangle* tri1 = new LDTriangle (getVertex (0), getVertex (1), getVertex (3));
 	LDTriangle* tri2 = new LDTriangle (getVertex (1), getVertex (2), getVertex (3));
-	
+
 	// The triangles also inherit the quad's color
 	tri1->setColor (color());
 	tri2->setColor (color());
-	
-	List<LDTriangle*> triangles;
+
+	QList<LDTriangle*> triangles;
 	triangles << tri1;
 	triangles << tri2;
 	return triangles;
@@ -216,27 +218,28 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDObject::replace (LDObject* other) {
-	long idx = getIndex();
+void LDObject::replace (LDObject* other)
+{	long idx = getIndex();
 	assert (idx != -1);
-	
+
 	// Replace the instance of the old object with the new object
 	file()->setObject (idx, other);
-	
+
 	// Remove the old object
 	delete this;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDObject::swap (LDObject* other) {
-	int i = 0;
-	for (LDObject* obj : file()->objects()) {
-		if (obj == this)
+void LDObject::swap (LDObject* other)
+{	int i = 0;
+
+	for (LDObject* obj : file()->objects())
+	{	if (obj == this)
 			file()->setObject (i, other);
 		elif (obj == other)
 			file()->setObject (i, this);
-		
+
 		++i;
 	}
 
@@ -245,131 +248,139 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-LDLine::LDLine (vertex v1, vertex v2) {
-	setVertex (0, v1);
+LDLine::LDLine (vertex v1, vertex v2)
+{	setVertex (0, v1);
 	setVertex (1, v2);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-LDObject::~LDObject() {
-	// Remove this object from the selection array if it is there.
-	for (ulong i = 0; i < g_win->sel().size(); ++i)
-		if (g_win->sel() [i] == this)
-			g_win->sel().erase (i);
-	
-	// Delete the GL lists
-	GL::deleteLists (this);
-	
-	// Remove this object from the list of LDObjects
-	ulong pos = g_LDObjects.find (this);
-	
-	if (pos < g_LDObjects.size())
-		g_LDObjects.erase (pos);
-	
-	g_vertexCompiler.forgetObject (this);
+LDQuad::LDQuad (const vertex& v0, const vertex& v1, const vertex& v2, const vertex& v3)
+{	setVertex (0, v0);
+	setVertex (1, v1);
+	setVertex (2, v2);
+	setVertex (3, v3);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-static void transformObject (LDObject* obj, matrix transform, vertex pos, short parentcolor) {
-	switch (obj->getType()) {
-	case LDObject::Line:
-	case LDObject::CndLine:
-	case LDObject::Triangle:
-	case LDObject::Quad:
-		for (short i = 0; i < obj->vertices(); ++i) {
-			vertex v = obj->getVertex (i);
-			v.transform (transform, pos);
-			obj->setVertex (i, v);
-		}
+LDObject::~LDObject()
+{	// If this object was selected, unselect it now
+	if (selected())
+		unselect();
+
+	// If this object was associated to a file, remove it off it now
+	if (file())
+		file()->forgetObject (this);
+
+	// Delete the GL lists
+	GL::deleteLists (this);
+
+	// Remove this object from the list of LDObjects
+	g_LDObjects.removeOne (this);
+}
 
-		break;
+// =============================================================================
+// -----------------------------------------------------------------------------
+static void transformObject (LDObject* obj, matrix transform, vertex pos, short parentcolor)
+{	switch (obj->getType())
+	{	case LDObject::Line:
+		case LDObject::CndLine:
+		case LDObject::Triangle:
+		case LDObject::Quad:
 
-	case LDObject::Subfile:
-		{
-			LDSubfile* ref = static_cast<LDSubfile*> (obj);
+			for (short i = 0; i < obj->vertices(); ++i)
+			{	vertex v = obj->getVertex (i);
+				v.transform (transform, pos);
+				obj->setVertex (i, v);
+			}
+
+			break;
+
+		case LDObject::Subfile:
+		{	LDSubfile* ref = static_cast<LDSubfile*> (obj);
 			matrix newMatrix = transform * ref->transform();
 			vertex newpos = ref->position();
-			
+
 			newpos.transform (transform, pos);
 			ref->setPosition (newpos);
 			ref->setTransform (newMatrix);
 		}
 		break;
 
-	default:
-		break;
+		default:
+			break;
 	}
-	
+
 	if (obj->color() == maincolor)
 		obj->setColor (parentcolor);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-List<LDObject*> LDSubfile::inlineContents (InlineFlags flags) {
-	List<LDObject*> objs = fileInfo()->inlineContents (flags);
-	
+QList<LDObject*> LDSubfile::inlineContents (InlineFlags flags)
+{	QList<LDObject*> objs = fileInfo()->inlineContents (flags);
+
 	// Transform the objects
-	for (LDObject* obj : objs) {
-		// Set the parent now so we know what inlined this.
+for (LDObject * obj : objs)
+	{	// Set the parent now so we know what inlined this.
 		obj->setParent (this);
 		transformObject (obj, transform(), position(), color());
 	}
-	
+
 	return objs;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-long LDObject::getIndex() const {
+long LDObject::getIndex() const
+{
 #ifndef RELEASE
 	assert (file() != null);
 #endif
-	
-	for (ulong i = 0; i < file()->numObjs(); ++i)
+
+	for (int i = 0; i < file()->numObjs(); ++i)
 		if (file()->obj (i) == this)
 			return i;
-	
+
 	return -1;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDObject::moveObjects (List<LDObject*> objs, const bool up) {
-	if (objs.size() == 0)
+void LDObject::moveObjects (QList<LDObject*> objs, const bool up)
+{	if (objs.isEmpty())
 		return;
-	
+
 	// If we move down, we need to iterate the array in reverse order.
 	const long start = up ? 0 : (objs.size() - 1);
 	const long end = up ? objs.size() : -1;
 	const long incr = up ? 1 : -1;
-	List<LDObject*> objsToCompile;
+	QList<LDObject*> objsToCompile;
 	LDFile* file = objs[0]->file();
-	
-	for (long i = start; i != end; i += incr) {
-		LDObject* obj = objs[i];
-		
+
+	for (long i = start; i != end; i += incr)
+	{	LDObject* obj = objs[i];
+
 		const long idx = obj->getIndex(),
-			target = idx + (up ? -1 : 1);
-		
-		if ((up && idx == 0) || (!up && idx == (long) (file->objects().size() - 1))) {
-			// One of the objects hit the extrema. If this happens, this should be the first
+				   target = idx + (up ? -1 : 1);
+
+		if ( (up && idx == 0) || (!up && idx == (long) (file->objects().size() - 1)))
+		{	// One of the objects hit the extrema. If this happens, this should be the first
 			// object to be iterated on. Thus, nothing has changed yet and it's safe to just
 			// abort the entire operation.
 			assert (i == start);
 			return;
 		}
-		
+
 		objsToCompile << obj;
 		objsToCompile << file->obj (target);
-		
+
 		obj->swap (file->obj (target));
 	}
-	
-	objsToCompile.makeUnique();
-	
+
+	removeDuplicates (objsToCompile);
+
 	// The objects need to be recompiled, otherwise their pick lists are left with
 	// the wrong index colors which messes up selection.
 	for (LDObject* obj : objsToCompile)
@@ -378,8 +389,8 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDObject::typeName (LDObject::Type type) {
-	LDObject* obj = LDObject::getDefault (type);
+str LDObject::typeName (LDObject::Type type)
+{	LDObject* obj = LDObject::getDefault (type);
 	str name = obj->typeName();
 	delete obj;
 	return name;
@@ -387,48 +398,49 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDObject::objectListContents (const List<LDObject*>& objs) {
-	bool firstDetails = true;
+str LDObject::objectListContents (const QList<LDObject*>& objs)
+{	bool firstDetails = true;
 	str text = "";
-	
-	if (objs.size() == 0)
+
+	if (objs.isEmpty())
 		return "nothing"; // :)
-	
-	for (long i = 0; i < LDObject::NumTypes; ++i) {
-		LDObject::Type objType = (LDObject::Type) i;
-		ulong objCount = 0;
-		
-		for (LDObject* obj : objs)
+
+	for (long i = 0; i < LDObject::NumTypes; ++i)
+	{	LDObject::Type objType = (LDObject::Type) i;
+		int count = 0;
+
+		for (LDObject * obj : objs)
 			if (obj->getType() == objType)
-				objCount++;
-		
-		if (objCount == 0)
+				count++;
+
+		if (count == 0)
 			continue;
-		
+
 		if (!firstDetails)
 			text += ", ";
-		
-		str noun = fmt ("%1%2", typeName (objType), plural (objCount));
+
+		str noun = fmt ("%1%2", typeName (objType), plural (count));
+
+		// Plural of "vertex" is "vertices", correct that
 		
-		// Plural of "vertex" is "vertices". Stupid English.
-		if (objType == LDObject::Vertex && objCount != 1)
+		if (objType == LDObject::Vertex && count != 1)
 			noun = "vertices";
-		
-		text += fmt ("%1 %2", objCount, noun);
+
+		text += fmt ("%1 %2", count, noun);
 		firstDetails = false;
 	}
-	
+
 	return text;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-LDObject* LDObject::topLevelParent() {
-	if (!parent())
+LDObject* LDObject::topLevelParent()
+{	if (!parent())
 		return this;
-	
+
 	LDObject* it = this;
-		
+
 	while (it->parent())
 		it = it->parent();
 
@@ -437,73 +449,83 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-LDObject* LDObject::next() const {
-	long idx = getIndex();
+LDObject* LDObject::next() const
+{	long idx = getIndex();
 	assert (idx != -1);
-	
+
 	if (idx == (long) file()->numObjs() - 1)
 		return null;
-	
+
 	return file()->obj (idx + 1);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-LDObject* LDObject::prev() const {
-	long idx = getIndex();
+LDObject* LDObject::prev() const
+{	long idx = getIndex();
 	assert (idx != -1);
-	
+
 	if (idx == 0)
 		return null;
-	
+
 	return file()->obj (idx - 1);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDObject::move (vertex vect)    { (void) vect; }
-void LDEmpty::move (vertex vect)     { (void) vect; }
-void LDBFC::move (vertex vect)       { (void) vect; }
-void LDComment::move (vertex vect)   { (void) vect; }
-void LDError::move (vertex vect) { (void) vect; }
-
-// =============================================================================
-// -----------------------------------------------------------------------------
-void LDVertex::move (vertex vect) {
-	pos += vect;
+void LDObject::move (vertex vect)
+{	(void) vect;
+}
+void LDEmpty::move (vertex vect)
+{	(void) vect;
+}
+void LDBFC::move (vertex vect)
+{	(void) vect;
+}
+void LDComment::move (vertex vect)
+{	(void) vect;
+}
+void LDError::move (vertex vect)
+{	(void) vect;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDSubfile::move (vertex vect) {
-	setPosition (position() + vect);
+void LDVertex::move (vertex vect)
+{	pos += vect;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDLine::move (vertex vect) {
-	for (short i = 0; i < 2; ++i)
+void LDSubfile::move (vertex vect)
+{	setPosition (position() + vect);
+}
+
+// =============================================================================
+// -----------------------------------------------------------------------------
+void LDLine::move (vertex vect)
+{	for (short i = 0; i < 2; ++i)
 		setVertex (i, getVertex (i) + vect);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDTriangle::move (vertex vect) {
-	for (short i = 0; i < 3; ++i)
+void LDTriangle::move (vertex vect)
+{	for (short i = 0; i < 3; ++i)
 		setVertex (i, getVertex (i) + vect);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDQuad::move (vertex vect) {
-	for (short i = 0; i < 4; ++i)
+void LDQuad::move (vertex vect)
+{	for (short i = 0; i < 4; ++i)
 		setVertex (i, getVertex (i) + vect);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDCndLine::move (vertex vect) {
-	for (short i = 0; i < 4; ++i)
+void LDCndLine::move (vertex vect)
+{	for (short i = 0; i < 4; ++i)
 		setVertex (i, getVertex (i) + vect);
 }
 
@@ -513,8 +535,8 @@
 	if (type == LDObject::N) \
 		return new LD##N;
 
-LDObject* LDObject::getDefault (const LDObject::Type type) {
-	CHECK_FOR_OBJ (Comment)
+LDObject* LDObject::getDefault (const LDObject::Type type)
+{	CHECK_FOR_OBJ (Comment)
 	CHECK_FOR_OBJ (BFC)
 	CHECK_FOR_OBJ (Line)
 	CHECK_FOR_OBJ (CndLine)
@@ -539,8 +561,8 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDTriangle::invert() {
-	// Triangle goes 0 -> 1 -> 2, reversed: 0 -> 2 -> 1.
+void LDTriangle::invert()
+{	// Triangle goes 0 -> 1 -> 2, reversed: 0 -> 2 -> 1.
 	// Thus, we swap 1 and 2.
 	vertex tmp = getVertex (1);
 	setVertex (1, getVertex (2));
@@ -551,8 +573,8 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDQuad::invert() {
-	// Quad: 0 -> 1 -> 2 -> 3
+void LDQuad::invert()
+{	// Quad: 0 -> 1 -> 2 -> 3
 	// rev:  0 -> 3 -> 2 -> 1
 	// Thus, we swap 1 and 3.
 	vertex tmp = getVertex (1);
@@ -562,26 +584,26 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-void LDSubfile::invert() {
-	// Subfiles are inverted when they're prefixed with
+void LDSubfile::invert()
+{	// Subfiles are inverted when they're prefixed with
 	// a BFC INVERTNEXT statement. Thus we need to toggle this status.
 	// For flat primitives it's sufficient that the determinant is
 	// flipped but I don't have a method for checking flatness yet.
 	// Food for thought...
-	
-	ulong idx = getIndex();
-	
-	if (idx > 0) {
-		LDBFC* bfc = dynamic_cast<LDBFC*> (prev());
-		
-		if (bfc && bfc->type == LDBFC::InvertNext) {
-			// This is prefixed with an invertnext, thus remove it.
+
+	int idx = getIndex();
+
+	if (idx > 0)
+	{	LDBFC* bfc = dynamic_cast<LDBFC*> (prev());
+
+		if (bfc && bfc->type == LDBFC::InvertNext)
+		{	// This is prefixed with an invertnext, thus remove it.
 			file()->forgetObject (bfc);
 			delete bfc;
 			return;
 		}
 	}
-	
+
 	// Not inverted, thus prefix it with a new invertnext.
 	LDBFC* bfc = new LDBFC (LDBFC::InvertNext);
 	file()->insertObj (idx, bfc);
@@ -589,57 +611,57 @@
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-static void invertLine (LDObject* line) {
-	// For lines, we swap the vertices. I don't think that a
+static void invertLine (LDObject* line)
+{	// For lines, we swap the vertices. I don't think that a
 	// cond-line's control points need to be swapped, do they?
 	vertex tmp = line->getVertex (0);
 	line->setVertex (0, line->getVertex (1));
 	line->setVertex (1, tmp);
 }
 
-void LDLine::invert() {
-	invertLine (this);
+void LDLine::invert()
+{	invertLine (this);
 }
 
-void LDCndLine::invert() {
-	invertLine (this);
+void LDCndLine::invert()
+{	invertLine (this);
 }
 
 void LDVertex::invert() {}
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-LDLine* LDCndLine::demote() {
-	LDLine* repl = new LDLine;
-	
+LDLine* LDCndLine::demote()
+{	LDLine* repl = new LDLine;
+
 	for (int i = 0; i < repl->vertices(); ++i)
 		repl->setVertex (i, getVertex (i));
-	
+
 	repl->setColor (color());
-	
+
 	replace (repl);
 	return repl;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-LDObject* LDObject::fromID (int id) {
-	for (LDObject* obj : g_LDObjects)
+LDObject* LDObject::fromID (int id)
+{	for (LDObject * obj : g_LDObjects)
 		if (obj->id() == id)
 			return obj;
-	
+
 	return null;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-str LDOverlay::raw() {
-	return fmt ("0 !LDFORGE OVERLAY %1 %2 %3 %4 %5 %6",
-		filename(), camera(), x(), y(), width(), height());
+str LDOverlay::raw()
+{	return fmt ("0 !LDFORGE OVERLAY %1 %2 %3 %4 %5 %6",
+				filename(), camera(), x(), y(), width(), height());
 }
 
-void LDOverlay::move (vertex vect) {
-	Q_UNUSED (vect)
+void LDOverlay::move (vertex vect)
+{	Q_UNUSED (vect)
 }
 
 void LDOverlay::invert() {}
@@ -649,55 +671,108 @@
 // It takes care of history management so we can capture low-level changes, this
 // makes history stuff work out of the box.
 // -----------------------------------------------------------------------------
-template<class T> void changeProperty (LDObject* obj, T* ptr, const T& val) {
-	long idx;
-	
-	if (obj->file() && (idx = obj->getIndex()) != -1) {
-		str before = obj->raw();
+template<class T> static void changeProperty (LDObject* obj, T* ptr, const T& val)
+{	long idx;
+
+	if (*ptr == val)
+		return;
+
+	if (obj->file() && (idx = obj->getIndex()) != -1)
+	{	str before = obj->raw();
 		*ptr = val;
 		str after = obj->raw();
-		
+
 		obj->file()->addToHistory (new EditHistory (idx, before, after));
-	} else
+	}
+	else
 		*ptr = val;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-READ_ACCESSOR (short, LDObject::color) {
-	return m_color;
+READ_ACCESSOR (short, LDObject::color)
+{	return m_color;
+}
+
+SET_ACCESSOR (short, LDObject::setColor)
+{	changeProperty (this, &m_color, val);
+}
+
+// =============================================================================
+// -----------------------------------------------------------------------------
+const vertex& LDObject::getVertex (int i) const
+{	return m_coords[i]->data();
 }
 
-SET_ACCESSOR (short, LDObject::setColor) {
-	changeProperty (this, &m_color, val);
+void LDObject::setVertex (int i, const vertex& vert)
+{	changeProperty (this, &m_coords[i], LDSharedVertex::getSharedVertex (vert));
+}
+
+// =============================================================================
+// -----------------------------------------------------------------------------
+void LDMatrixObject::setPosition (const vertex& a)
+{	changeProperty (linkPointer(), &m_position, LDSharedVertex::getSharedVertex (a));
+}
+
+// =============================================================================
+// -----------------------------------------------------------------------------
+READ_ACCESSOR (matrix, LDMatrixObject::transform)
+{	return m_transform;
+}
+
+SET_ACCESSOR (matrix, LDMatrixObject::setTransform)
+{	changeProperty (linkPointer(), &m_transform, val);
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-const vertex& LDObject::getVertex (int i) const {
-	return m_coords[i];
+static QMap<vertex, LDSharedVertex*> g_sharedVerts;
+
+LDSharedVertex* LDSharedVertex::getSharedVertex (const vertex& a)
+{	auto it = g_sharedVerts.find (a);
+
+	if (it == g_sharedVerts.end())
+	{	LDSharedVertex* v = new LDSharedVertex (a);
+		g_sharedVerts[a] = v;
+		return v;
+	}
+
+	return *it;
 }
 
-void LDObject::setVertex (int i, const vertex& vert) {
-	changeProperty (this, &m_coords[i], vert);
+// =============================================================================
+// -----------------------------------------------------------------------------
+void LDSharedVertex::addRef (LDObject* a)
+{	m_refs << a;
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-READ_ACCESSOR (vertex, LDMatrixObject::position) {
-	return m_position;
-}
+void LDSharedVertex::delRef (LDObject* a)
+{	m_refs.removeOne (a);
 
-SET_ACCESSOR (vertex, LDMatrixObject::setPosition) {
-	changeProperty (linkPointer(), &m_position, val);
+	if (m_refs.empty())
+	{	g_sharedVerts.remove (m_data);
+		delete this;
+	}
 }
 
 // =============================================================================
 // -----------------------------------------------------------------------------
-READ_ACCESSOR (matrix, LDMatrixObject::transform) {
-	return m_transform;
+void LDObject::select()
+{	if (!file())
+	{	log ("Warning: Object #%1 cannot be selected as it is not assigned a file!\n", id());
+		return;
+	}
+
+	file()->addToSelection (this);
 }
 
-SET_ACCESSOR (matrix, LDMatrixObject::setTransform) {
-	changeProperty (linkPointer(), &m_transform, val);
+void LDObject::unselect()
+{	if (!file())
+	{	log ("Warning: Object #%1 cannot be unselected as it is not assigned a file!\n", id());
+		return;
+	}
+
+	file()->removeFromSelection (this);
 }
\ No newline at end of file

mercurial