Renamed ldObject.cpp → linetypes/modelobject.cpp

Tue, 14 Feb 2017 14:59:26 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Tue, 14 Feb 2017 14:59:26 +0200
changeset 1147
a26568aa3cce
parent 1146
bb728c124d47
child 1148
96cb15a7611f

Renamed ldObject.cpp → linetypes/modelobject.cpp

CMakeLists.txt file | annotate | diff | comparison | revisions
src/basics.cpp file | annotate | diff | comparison | revisions
src/dialogs/generateprimitivedialog.cpp file | annotate | diff | comparison | revisions
src/dialogs/newpartdialog.h file | annotate | diff | comparison | revisions
src/documentloader.cpp file | annotate | diff | comparison | revisions
src/editHistory.cpp file | annotate | diff | comparison | revisions
src/editHistory.h file | annotate | diff | comparison | revisions
src/editmodes/circleMode.cpp file | annotate | diff | comparison | revisions
src/editmodes/curvemode.cpp file | annotate | diff | comparison | revisions
src/editmodes/drawMode.cpp file | annotate | diff | comparison | revisions
src/editmodes/rectangleMode.cpp file | annotate | diff | comparison | revisions
src/ldObject.cpp file | annotate | diff | comparison | revisions
src/ldObject.h file | annotate | diff | comparison | revisions
src/lddocument.h file | annotate | diff | comparison | revisions
src/ldobjectiterator.h file | annotate | diff | comparison | revisions
src/linetypes/comment.h file | annotate | diff | comparison | revisions
src/linetypes/edgeline.h file | annotate | diff | comparison | revisions
src/linetypes/empty.h file | annotate | diff | comparison | revisions
src/linetypes/modelobject.cpp file | annotate | diff | comparison | revisions
src/linetypes/modelobject.h file | annotate | diff | comparison | revisions
src/mainwindow.h file | annotate | diff | comparison | revisions
src/mathfunctions.cpp file | annotate | diff | comparison | revisions
src/model.cpp file | annotate | diff | comparison | revisions
src/model.h file | annotate | diff | comparison | revisions
src/toolsets/basictoolset.cpp file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Tue Feb 14 14:53:06 2017 +0200
+++ b/CMakeLists.txt	Tue Feb 14 14:59:26 2017 +0200
@@ -42,7 +42,6 @@
 	src/guiutilities.cpp
 	src/hierarchyelement.cpp
 	src/lddocument.cpp
-	src/ldObject.cpp
 	src/ldpaths.cpp
 	src/main.cpp
 	src/mainwindow.cpp
@@ -76,6 +75,7 @@
 	src/linetypes/conditionaledge.cpp
 	src/linetypes/edgeline.cpp
 	src/linetypes/empty.cpp
+	src/linetypes/modelobject.cpp
 	src/toolsets/algorithmtoolset.cpp
 	src/toolsets/basictoolset.cpp
 	src/toolsets/extprogramtoolset.cpp
@@ -104,7 +104,6 @@
 	src/guiutilities.h
 	src/hierarchyelement.h
 	src/lddocument.h
-	src/ldObject.h
 	src/ldobjectiterator.h
 	src/ldpaths.h
 	src/macros.h
@@ -140,6 +139,7 @@
 	src/linetypes/conditionaledge.h
 	src/linetypes/edgeline.h
 	src/linetypes/empty.h
+	src/linetypes/modelobject.h
 	src/toolsets/algorithmtoolset.h
 	src/toolsets/basictoolset.h
 	src/toolsets/extprogramtoolset.h
--- a/src/basics.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/basics.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -17,7 +17,7 @@
  */
 
 #include "miscallenous.h"
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 #include "lddocument.h"
 
 Vertex::Vertex() :
--- a/src/dialogs/generateprimitivedialog.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/dialogs/generateprimitivedialog.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -16,7 +16,7 @@
  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 #include "generateprimitivedialog.h"
 #include "ui_generateprimitivedialog.h"
 
--- a/src/dialogs/newpartdialog.h	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/dialogs/newpartdialog.h	Tue Feb 14 14:59:26 2017 +0200
@@ -19,7 +19,7 @@
 #pragma once
 #include <QDialog>
 #include "../main.h"
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 
 class NewPartDialog : public QDialog, HierarchyElement
 {
--- a/src/documentloader.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/documentloader.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -18,7 +18,7 @@
 
 #include "documentloader.h"
 #include "lddocument.h"
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 #include "mainwindow.h"
 #include "dialogs/openprogressdialog.h"
 
--- a/src/editHistory.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/editHistory.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -17,7 +17,7 @@
  */
 
 #include "editHistory.h"
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 #include "lddocument.h"
 #include "miscallenous.h"
 #include "mainwindow.h"
--- a/src/editHistory.h	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/editHistory.h	Tue Feb 14 14:59:26 2017 +0200
@@ -18,7 +18,7 @@
 
 #pragma once
 #include "main.h"
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 
 class AbstractHistoryEntry;
 
--- a/src/editmodes/circleMode.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/editmodes/circleMode.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -19,7 +19,7 @@
 #include <QPainter>
 #include "circleMode.h"
 #include "../miscallenous.h"
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 #include "../lddocument.h"
 #include "../ringFinder.h"
 #include "../primitives.h"
--- a/src/editmodes/curvemode.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/editmodes/curvemode.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -17,7 +17,7 @@
  */
 
 #include "curvemode.h"
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 #include "../canvas.h"
 
 CurveMode::CurveMode (Canvas* canvas) :
--- a/src/editmodes/drawMode.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/editmodes/drawMode.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -19,7 +19,7 @@
 #include <QPainter>
 #include <QMouseEvent>
 #include "drawMode.h"
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 #include "../glrenderer.h"
 #include "../linetypes/edgeline.h"
 
--- a/src/editmodes/rectangleMode.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/editmodes/rectangleMode.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -19,7 +19,7 @@
 #include <QPainter>
 #include <QMouseEvent>
 #include "rectangleMode.h"
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 #include "../canvas.h"
 
 RectangleMode::RectangleMode (Canvas* canvas) :
--- a/src/ldObject.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,825 +0,0 @@
-/*
- *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 - 2017 Teemu Piippo
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <assert.h>
-#include "documentmanager.h"
-#include "ldObject.h"
-#include "lddocument.h"
-#include "miscallenous.h"
-#include "mainwindow.h"
-#include "editHistory.h"
-#include "canvas.h"
-#include "colors.h"
-#include "glcompiler.h"
-#include "linetypes/edgeline.h"
-
-// List of all LDObjects
-QMap<qint32, LDObject*> g_allObjects;
-
-enum { MAX_LDOBJECT_IDS = (1 << 24) };
-
-#define LDOBJ_DEFAULT_CTOR(T,BASE) \
-	T :: T (Model* model) : \
-	    BASE {model} {}
-
-// =============================================================================
-// LDObject constructors
-//
-LDObject::LDObject (Model* model) :
-    m_isHidden {false},
-    m_isSelected {false},
-    _model {model},
-    m_coords {Origin}
-{
-	assert(_model != nullptr);
-
-	// Let's hope that nobody goes to create 17 million objects anytime soon...
-	static qint32 nextId = 1; // 0 shalt be null
-	if (nextId < MAX_LDOBJECT_IDS)
-		m_id = nextId++;
-	else
-		m_id = 0;
-
-	if (m_id != 0)
-		g_allObjects[m_id] = this;
-
-	m_randomColor = QColor::fromHsv (rand() % 360, rand() % 256, rand() % 96 + 128);
-}
-
-LDSubfileReference::LDSubfileReference (Model* model) :
-    LDMatrixObject (model) {}
-
-LDOBJ_DEFAULT_CTOR (LDError, LDObject)
-LDOBJ_DEFAULT_CTOR (LDTriangle, LDObject)
-LDOBJ_DEFAULT_CTOR (LDQuadrilateral, LDObject)
-LDOBJ_DEFAULT_CTOR (LDBfc, LDObject)
-LDOBJ_DEFAULT_CTOR (LDBezierCurve, LDObject)
-
-LDObject::~LDObject()
-{
-	// Delete the GL lists
-	if (g_win)
-		g_win->renderer()->forgetObject(this);
-
-	// Remove this object from the list of LDObjects
-	g_allObjects.erase(g_allObjects.find(id()));
-}
-
-// =============================================================================
-//
-QString LDSubfileReference::asText() const
-{
-	QString val = format ("1 %1 %2 ", color(), position());
-	val += transformationMatrix().toString();
-	val += ' ';
-	val += fileInfo()->name();
-	return val;
-}
-
-// =============================================================================
-//
-QString LDTriangle::asText() const
-{
-	QString val = format ("3 %1", color());
-
-	for (int i = 0; i < 3; ++i)
-		val += format (" %1", vertex (i));
-
-	return val;
-}
-
-// =============================================================================
-//
-QString LDQuadrilateral::asText() const
-{
-	QString val = format ("4 %1", color());
-
-	for (int i = 0; i < 4; ++i)
-		val += format (" %1", vertex (i));
-
-	return val;
-}
-
-QString LDBezierCurve::asText() const
-{
-	QString result = format ("0 !LDFORGE BEZIER_CURVE %1", color());
-
-	// Add the coordinates
-	for (int i = 0; i < 4; ++i)
-		result += format (" %1", vertex (i));
-
-	return result;
-}
-
-// =============================================================================
-//
-QString LDError::asText() const
-{
-	return contents();
-}
-
-// =============================================================================
-//
-QString LDBfc::asText() const
-{
-	return format ("0 BFC %1", statementToString());
-}
-
-// =============================================================================
-//
-// Swap this object with another.
-//
-void LDObject::swap (LDObject* other)
-{
-	if (model() == other->model())
-		model()->swapObjects (this, other);
-}
-
-int LDObject::triangleCount() const
-{
-	return 0;
-}
-
-int LDSubfileReference::triangleCount() const
-{
-	return fileInfo()->triangleCount();
-}
-
-int LDTriangle::triangleCount() const
-{
-	return 1;
-}
-
-int LDQuadrilateral::triangleCount() const
-{
-	return 2;
-}
-
-int LDObject::numVertices() const
-{
-	return 0;
-}
-
-// =============================================================================
-//
-LDTriangle::LDTriangle (const Vertex& v1, const Vertex& v2, const Vertex& v3, Model* model) :
-    LDObject {model}
-{
-	setVertex (0, v1);
-	setVertex (1, v2);
-	setVertex (2, v3);
-}
-
-// =============================================================================
-//
-LDQuadrilateral::LDQuadrilateral (const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex& v4, Model* model) :
-    LDObject {model}
-{
-	setVertex (0, v1);
-	setVertex (1, v2);
-	setVertex (2, v3);
-	setVertex (3, v4);
-}
-
-// =============================================================================
-//
-LDBezierCurve::LDBezierCurve(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3, Model* model) :
-    LDObject {model}
-{
-	setVertex (0, v0);
-	setVertex (1, v1);
-	setVertex (2, v2);
-	setVertex (3, v3);
-}
-
-// =============================================================================
-//
-void LDObject::setDocument (Model* model)
-{
-	_model = model;
-}
-
-// =============================================================================
-//
-static void TransformObject (LDObject* obj, Matrix transform, Vertex pos, LDColor parentcolor)
-{
-	switch (obj->type())
-	{
-	case LDObjectType::EdgeLine:
-	case LDObjectType::ConditionalEdge:
-	case LDObjectType::Triangle:
-	case LDObjectType::Quadrilateral:
-		for (int i = 0; i < obj->numVertices(); ++i)
-		{
-			Vertex v = obj->vertex (i);
-			v.transform (transform, pos);
-			obj->setVertex (i, v);
-		}
-		break;
-
-	case LDObjectType::SubfileReference:
-		{
-			LDSubfileReference* ref = static_cast<LDSubfileReference*> (obj);
-			Matrix newMatrix = transform * ref->transformationMatrix();
-			Vertex newpos = ref->position();
-			newpos.transform (transform, pos);
-			ref->setPosition (newpos);
-			ref->setTransformationMatrix (newMatrix);
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	if (obj->color() == MainColor)
-		obj->setColor (parentcolor);
-}
-
-// =============================================================================
-// -----------------------------------------------------------------------------
-void LDSubfileReference::inlineContents(Model& model, bool deep, bool render)
-{
-	Model inlined {this->model()->documentManager()};
-	fileInfo()->inlineContents(inlined, deep, render);
-
-	// Transform the objects
-	for (LDObject* object : inlined)
-		TransformObject(object, transformationMatrix(), position(), color());
-
-	model.merge(inlined);
-}
-
-// =============================================================================
-//
-LDPolygon* LDObject::getPolygon()
-{
-	LDObjectType ot = type();
-	int num = (ot == LDObjectType::EdgeLine)		? 2
-			: (ot == LDObjectType::Triangle)	? 3
-			: (ot == LDObjectType::Quadrilateral)		? 4
-			: (ot == LDObjectType::ConditionalEdge)	? 5
-			: 0;
-
-	if (num == 0)
-		return nullptr;
-
-	LDPolygon* data = new LDPolygon;
-	data->id = id();
-	data->num = num;
-	data->color = color().index();
-
-	for (int i = 0; i < data->numVertices(); ++i)
-		data->vertices[i] = vertex (i);
-
-	return data;
-}
-
-LDColor LDObject::defaultColor() const
-{
-	return MainColor;
-}
-
-bool LDObject::isColored() const
-{
-	return true;
-}
-
-bool LDObject::isScemantic() const
-{
-	return true;
-}
-
-bool LDObject::hasMatrix() const
-{
-	return false;
-}
-
-// =============================================================================
-//
-QList<LDPolygon> LDSubfileReference::inlinePolygons()
-{
-	QList<LDPolygon> data = fileInfo()->inlinePolygons();
-
-	for (LDPolygon& entry : data)
-	{
-		for (int i = 0; i < entry.numVertices(); ++i)
-			entry.vertices[i].transform (transformationMatrix(), position());
-	}
-
-	return data;
-}
-
-// =============================================================================
-//
-// Index (i.e. line number) of this object
-//
-int LDObject::lineNumber() const
-{
-	if (model())
-	{
-		for (int i = 0; i < model()->size(); ++i)
-		{
-			if (model()->getObject(i) == this)
-				return i;
-		}
-	}
-
-	return -1;
-}
-
-// =============================================================================
-//
-// Object after this in the current file
-//
-LDObject* LDObject::next() const
-{
-	return model()->getObject(lineNumber() + 1);
-}
-
-// =============================================================================
-//
-// Object prior to this in the current file
-//
-LDObject* LDObject::previous() const
-{
-	return model()->getObject(lineNumber() - 1);
-}
-
-// =============================================================================
-//
-// Is the previous object INVERTNEXT?
-//
-bool LDObject::previousIsInvertnext (LDBfc*& ptr)
-{
-	LDObject* prev = previous();
-
-	if (prev and prev->type() == LDObjectType::Bfc and static_cast<LDBfc*> (prev)->statement() == BfcStatement::InvertNext)
-	{
-		ptr = static_cast<LDBfc*> (prev);
-		return true;
-	}
-
-	return false;
-}
-
-// =============================================================================
-//
-// Moves this object using the given vertex as a movement List
-//
-void LDObject::move (Vertex vect)
-{
-	if (hasMatrix())
-	{
-		LDMatrixObject* mo = static_cast<LDMatrixObject*> (this);
-		mo->setPosition (mo->position() + vect);
-	}
-	else
-	{
-		for (int i = 0; i < numVertices(); ++i)
-			setVertex (i, vertex (i) + vect);
-	}
-}
-
-bool LDObject::isHidden() const
-{
-	return m_isHidden;
-}
-
-void LDObject::setHidden (bool value)
-{
-	m_isHidden = value;
-}
-
-bool LDObject::isSelected() const
-{
-	return m_isSelected;
-}
-
-qint32 LDObject::id() const
-{
-	return m_id;
-}
-
-LDColor LDObject::color() const
-{
-	return m_color;
-}
-
-QColor LDObject::randomColor() const
-{
-	return m_randomColor;
-}
-
-Model* LDObject::model() const
-{
-	return _model;
-}
-
-// =============================================================================
-//
-void LDObject::invert() {}
-void LDBfc::invert() {}
-void LDError::invert() {}
-
-// =============================================================================
-//
-void LDTriangle::invert()
-{
-	// Triangle goes 0 -> 1 -> 2, reversed: 0 -> 2 -> 1.
-	// Thus, we swap 1 and 2.
-	Vertex tmp = vertex (1);
-	setVertex (1, vertex (2));
-	setVertex (2, tmp);
-
-	return;
-}
-
-// =============================================================================
-//
-void LDQuadrilateral::invert()
-{
-	// Quad:     0 -> 1 -> 2 -> 3
-	// reversed: 0 -> 3 -> 2 -> 1
-	// Thus, we swap 1 and 3.
-	Vertex tmp = vertex (1);
-	setVertex (1, vertex (3));
-	setVertex (3, tmp);
-}
-
-// =============================================================================
-//
-void LDSubfileReference::invert()
-{
-	if (model() == nullptr)
-		return;
-
-	// Check whether subfile is flat
-	int axisSet = (1 << X) | (1 << Y) | (1 << Z);
-	Model model {this->model()->documentManager()};
-	fileInfo()->inlineContents(model, true, false);
-
-	for (LDObject* obj : model.objects())
-	{
-		for (int i = 0; i < obj->numVertices(); ++i)
-		{
-			Vertex const& vrt = obj->vertex (i);
-
-			if (axisSet & (1 << X) and vrt.x() != 0.0)
-				axisSet &= ~(1 << X);
-
-			if (axisSet & (1 << Y) and vrt.y() != 0.0)
-				axisSet &= ~(1 << Y);
-
-			if (axisSet & (1 << Z) and vrt.z() != 0.0)
-				axisSet &= ~(1 << Z);
-		}
-
-		if (axisSet == 0)
-			break;
-	}
-
-	if (axisSet != 0)
-	{
-		// Subfile has all vertices zero on one specific plane, so it is flat.
-		// Let's flip it.
-		Matrix matrixModifier = Matrix::identity;
-
-		if (axisSet & (1 << X))
-			matrixModifier(0, 0) = -1;
-
-		if (axisSet & (1 << Y))
-			matrixModifier(1, 1) = -1;
-
-		if (axisSet & (1 << Z))
-			matrixModifier(2, 2) = -1;
-
-		setTransformationMatrix (transformationMatrix() * matrixModifier);
-		return;
-	}
-
-	// Subfile is not flat. Resort to invertnext.
-	int idx = lineNumber();
-
-	if (idx > 0)
-	{
-		LDBfc* bfc = dynamic_cast<LDBfc*> (previous());
-
-		if (bfc and bfc->statement() == BfcStatement::InvertNext)
-		{
-			// This is prefixed with an invertnext, thus remove it.
-			this->model()->remove(bfc);
-			return;
-		}
-	}
-
-	// Not inverted, thus prefix it with a new invertnext.
-	this->model()->emplaceAt<LDBfc>(idx, BfcStatement::InvertNext);
-}
-
-// =============================================================================
-//
-void LDBezierCurve::invert()
-{
-	// A Bézier curve's control points probably need to be, though.
-	Vertex tmp = vertex (1);
-	setVertex (1, vertex (0));
-	setVertex (0, tmp);
-	tmp = vertex (3);
-	setVertex (3, vertex (2));
-	setVertex (2, tmp);
-}
-
-// =============================================================================
-//
-LDObject* LDObject::fromID(qint32 id)
-{
-	return g_allObjects.value(id);
-}
-
-// =============================================================================
-//
-void LDObject::setColor (LDColor color)
-{
-	changeProperty(&m_color, color);
-}
-
-// =============================================================================
-//
-// Get a vertex by index
-//
-const Vertex& LDObject::vertex (int i) const
-{
-	return m_coords[i];
-}
-
-// =============================================================================
-//
-// Set a vertex to the given value
-//
-void LDObject::setVertex (int i, const Vertex& vert)
-{
-	changeProperty(&m_coords[i], vert);
-}
-
-LDMatrixObject::LDMatrixObject (Model* model) :
-    LDObject (model),
-	m_position (Origin) {}
-
-LDMatrixObject::LDMatrixObject (const Matrix& transform, const Vertex& pos, Model* model) :
-    LDObject (model),
-	m_position (pos),
-	m_transformationMatrix (transform) {}
-
-void LDMatrixObject::setCoordinate (const Axis ax, double value)
-{
-	Vertex v = position();
-
-	switch (ax)
-	{
-		case X: v.setX (value); break;
-		case Y: v.setY (value); break;
-		case Z: v.setZ (value); break;
-	}
-
-	setPosition (v);
-}
-
-const Vertex& LDMatrixObject::position() const
-{
-	return m_position;
-}
-
-// =============================================================================
-//
-void LDMatrixObject::setPosition (const Vertex& a)
-{
-	changeProperty(&m_position, a);
-}
-
-// =============================================================================
-//
-const Matrix& LDMatrixObject::transformationMatrix() const
-{
-	return m_transformationMatrix;
-}
-
-void LDMatrixObject::setTransformationMatrix (const Matrix& val)
-{
-	changeProperty(&m_transformationMatrix, val);
-}
-
-LDError::LDError (QString contents, QString reason, Model* model) :
-    LDObject (model),
-	m_contents (contents),
-	m_reason (reason) {}
-
-QString LDError::reason() const
-{
-	return m_reason;
-}
-
-QString LDError::contents() const
-{
-	return m_contents;
-}
-
-QString LDError::fileReferenced() const
-{
-	return m_fileReferenced;
-}
-
-void LDError::setFileReferenced (QString value)
-{
-	m_fileReferenced = value;
-}
-
-LDBfc::LDBfc (const BfcStatement type, Model* model) :
-    LDObject {model},
-    m_statement {type} {}
-
-BfcStatement LDBfc::statement() const
-{
-	return m_statement;
-}
-
-void LDBfc::setStatement (BfcStatement value)
-{
-	m_statement = value;
-}
-
-QString LDBfc::statementToString() const
-{
-	return LDBfc::statementToString (statement());
-}
-
-QString LDBfc::statementToString (BfcStatement statement)
-{
-	static const char* statementStrings[] =
-	{
-		"CERTIFY CCW",
-		"CCW",
-		"CERTIFY CW",
-		"CW",
-		"NOCERTIFY",
-		"INVERTNEXT",
-		"CLIP",
-		"CLIP CCW",
-		"CLIP CW",
-		"NOCLIP",
-	};
-
-	if ((int) statement >= 0 and (int) statement < countof (statementStrings))
-		return QString::fromLatin1 (statementStrings[(int) statement]);
-	else
-		return "";
-}
-
-Vertex LDBezierCurve::pointAt (qreal t) const
-{
-	if (t >= 0.0 and t <= 1.0)
-	{
-		Vertex result;
-		result += pow (1.0 - t, 3) * vertex (0);
-		result += (3 * pow (1.0 - t, 2) * t) * vertex (2);
-		result += (3 * (1.0 - t) * pow (t, 2)) * vertex (3);
-		result += pow (t, 3) * vertex (1);
-		return result;
-	}
-	else
-		return Vertex();
-}
-
-void LDBezierCurve::rasterize(Model& model, int segments)
-{
-	QVector<LDPolygon> polygons = rasterizePolygons(segments);
-
-	for (LDPolygon& poly : polygons)
-	{
-		LDEdgeLine* line = model.emplace<LDEdgeLine>(poly.vertices[0], poly.vertices[1]);
-		line->setColor (poly.color);
-	}
-}
-
-QVector<LDPolygon> LDBezierCurve::rasterizePolygons(int segments)
-{
-	QVector<LDPolygon> result;
-	QVector<Vertex> parms;
-	parms.append (pointAt (0.0));
-
-	for (int i = 1; i < segments; ++i)
-		parms.append (pointAt (double (i) / segments));
-
-	parms.append (pointAt (1.0));
-	LDPolygon poly;
-	poly.color = color().index();
-	poly.id = id();
-	poly.num = 2;
-
-	for (int i = 0; i < segments; ++i)
-	{
-		poly.vertices[0] = parms[i];
-		poly.vertices[1] = parms[i + 1];
-		result << poly;
-	}
-
-	return result;
-}
-
-LDSubfileReference::LDSubfileReference(LDDocument* reference, const Matrix& transformationMatrix,
-                                       const Vertex& position, Model* model) :
-    LDMatrixObject {transformationMatrix, position, model},
-    m_fileInfo {reference} {}
-
-// =============================================================================
-//
-LDDocument* LDSubfileReference::fileInfo() const
-{
-	return m_fileInfo;
-}
-
-void LDSubfileReference::setFileInfo (LDDocument* newReferee)
-{
-	changeProperty(&m_fileInfo, newReferee);
-
-	if (model())
-		model()->recountTriangles();
-
-	// If it's an immediate subfile reference (i.e. this subfile is in an opened document), we need to pre-compile the
-	// GL polygons for the document if they don't exist already.
-	if (newReferee and
-		newReferee->isFrozen() == false and
-		newReferee->polygonData().isEmpty())
-	{
-		newReferee->initializeCachedData();
-	}
-}
-
-void LDObject::getVertices (QSet<Vertex>& verts) const
-{
-	for (int i = 0; i < numVertices(); ++i)
-		verts.insert(vertex(i));
-}
-
-void LDSubfileReference::getVertices (QSet<Vertex>& verts) const
-{
-	verts.unite(fileInfo()->inlineVertices());
-}
-
-QString LDObject::objectListText() const
-{
-	if (numVertices() > 0)
-	{
-		QString result;
-
-		for (int i = 0; i < numVertices(); ++i)
-		{
-			if (i != 0)
-				result += ", ";
-
-			result += vertex(i).toString (true);
-		}
-
-		return result;
-	}
-	else
-	{
-		return typeName();
-	}
-}
-
-QString LDError::objectListText() const
-{
-	return "ERROR: " + asText();
-}
-
-QString LDSubfileReference::objectListText() const
-{
-	QString result = format ("%1 %2, (", fileInfo()->getDisplayName(), position().toString(true));
-
-	for (int i = 0; i < 9; ++i)
-		result += format("%1%2", transformationMatrix().value(i), (i != 8) ? " " : "");
-
-	result += ')';
-	return result;
-}
-
-QString LDBfc::objectListText() const
-{
-	return statementToString();
-}
--- a/src/ldObject.h	Tue Feb 14 14:53:06 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,351 +0,0 @@
-/*
- *  LDForge: LDraw parts authoring CAD
- *  Copyright (C) 2013 - 2017 Teemu Piippo
- *
- *  This program is free software: you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation, either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-#include <type_traits>
-#include "main.h"
-#include "basics.h"
-#include "glShared.h"
-#include "colors.h"
-
-class Model;
-class LDDocument;
-
-/*
- * Object type codes.
- */
-enum LDObjectType
-{
-	SubfileReference,	//	Object represents a	sub-file reference
-	Quadrilateral,		//	Object represents a	quadrilateral
-	Triangle,			//	Object represents a	triangle
-	EdgeLine,			//	Object represents a	line
-	ConditionalEdge,	//	Object represents a	conditional line
-	Bfc,				//	Object represents a	BFC statement
-	Comment,			//	Object represents a	comment
-	Error,				//	Object is the result of failed parsing
-	Empty,				//	Object represents an empty line
-	BezierCurve,		//	Object represents a Bézier curve
-	_End
-};
-
-MAKE_ITERABLE_ENUM(LDObjectType)
-
-/*
- * Represents one line of code in an LDraw model file.
- */
-class LDObject : public QObject
-{
-	Q_OBJECT
-
-public:
-	virtual QString asText() const = 0; // This object as LDraw code
-	LDColor color() const;
-	virtual LDColor defaultColor() const; // What color does the object default to?
-	Model* model() const;
-	LDPolygon* getPolygon();
-	virtual void getVertices (QSet<Vertex>& verts) const;
-	virtual bool hasMatrix() const; // Does this object have a matrix and position? (see LDMatrixObject)
-	qint32 id() const;
-	virtual void invert(); // Inverts this object (winding is reversed)
-	virtual bool isColored() const;
-	bool isHidden() const;
-	virtual bool isScemantic() const; // Does this object have meaning in the part model?
-	bool isSelected() const;
-	int lineNumber() const;
-	void move (Vertex vect);
-	LDObject* next() const;
-	virtual int numVertices() const;
-	virtual QString objectListText() const;
-	LDObject* previous() const;
-	bool previousIsInvertnext(class LDBfc*& ptr);
-	QColor randomColor() const;
-	void setColor (LDColor color);
-	void setHidden (bool value);
-	void setVertex (int i, const Vertex& vert);
-	void swap (LDObject* other);
-	virtual int triangleCount() const;
-	virtual LDObjectType type() const = 0;
-	virtual QString typeName() const = 0;
-	const Vertex& vertex (int i) const;
-
-	static LDObject* fromID(qint32 id);
-
-signals:
-	void codeChanged(QString before, QString after);
-
-protected:
-	friend class Model;
-	LDObject (Model* model = nullptr);
-	virtual ~LDObject();
-	void setDocument(Model* model);
-
-	template<typename T>
-	void changeProperty(T* property, const T& value);
-
-private:
-	bool m_isHidden;
-	bool m_isSelected;
-	Model* _model;
-	qint32 m_id;
-	LDColor m_color;
-	QColor m_randomColor;
-	Vertex m_coords[4];
-};
-
-/*
- * Base class for objects with matrices.
- */
-class LDMatrixObject : public LDObject
-{
-	Vertex m_position;
-
-public:
-	const Vertex& position() const;
-	void setCoordinate (const Axis ax, double value);
-	void setPosition (const Vertex& a);
-	void setTransformationMatrix (const Matrix& value);
-	const Matrix& transformationMatrix() const;
-
-protected:
-	LDMatrixObject (Model* model = nullptr);
-	LDMatrixObject (const Matrix& transformationMatrix, const Vertex& pos, Model* model = nullptr);
-
-private:
-	Matrix m_transformationMatrix;
-};
-
-/*
- * Represents a line in the LDraw file that could not be properly parsed.
- */
-class LDError : public LDObject
-{
-public:
-	static constexpr LDObjectType SubclassType = LDObjectType::Error;
-
-	virtual LDObjectType type() const override
-	{
-		return SubclassType;
-	}
-
-	virtual QString asText() const override;
-	virtual void invert() override;
-	QString reason() const;
-	QString contents() const;
-	QString fileReferenced() const;
-	void setFileReferenced (QString value);
-	QString objectListText() const override;
-	bool isColored() const override { return false; }
-	QString typeName() const override { return "error"; }
-
-protected:
-	friend class Model;
-	LDError (Model* model);
-	LDError (QString contents, QString reason, Model* model = nullptr);
-
-private:
-	QString m_fileReferenced; // If this error was caused by inability to open a file, what file was that?
-	QString m_contents; // The LDraw code that was being parsed
-	QString m_reason;
-};
-
-/*
- * Represents a 0 BFC statement in the LDraw code.
- */
-enum class BfcStatement
-{
-	CertifyCCW,
-	CCW,
-	CertifyCW,
-	CW,
-	NoCertify,
-	InvertNext,
-	Clip,
-	ClipCCW,
-	ClipCW,
-	NoClip,
-	_End
-};
-
-MAKE_ITERABLE_ENUM(BfcStatement)
-
-class LDBfc : public LDObject
-{
-	public:
-	static constexpr LDObjectType SubclassType = LDObjectType::Bfc;
-
-	virtual LDObjectType type() const override
-	{
-		return SubclassType;
-	}
-
-	virtual QString asText() const override;
-	virtual void invert() override;
-protected:
-	friend class Model;
-	LDBfc (Model* model);
-
-public:
-	bool isScemantic() const override { return statement() == BfcStatement::InvertNext; }
-    QString objectListText() const override;
-	BfcStatement statement() const;
-	void setStatement (BfcStatement value);
-	QString statementToString() const;
-	bool isColored() const override { return false; }
-	QString typeName() const override { return "bfc"; }
-
-	static QString statementToString (BfcStatement statement);
-
-protected:
-	LDBfc (const BfcStatement type, Model* model = nullptr);
-
-private:
-	BfcStatement m_statement;
-};
-
-/*
- * Represents a single code-1 subfile reference.
- */
-class LDSubfileReference : public LDMatrixObject
-{
-public:
-	static constexpr LDObjectType SubclassType = LDObjectType::SubfileReference;
-
-	virtual LDObjectType type() const override
-	{
-		return SubclassType;
-	}
-
-	virtual QString asText() const override;
-	virtual void invert() override;
-	LDDocument* fileInfo() const;
-	virtual void getVertices (QSet<Vertex>& verts) const override;
-	void inlineContents(Model& model, bool deep, bool render);
-	QList<LDPolygon> inlinePolygons();
-	QString objectListText() const override;
-	void setFileInfo (LDDocument* fileInfo);
-	int triangleCount() const override;
-	bool hasMatrix() const override { return true; }
-	QString typeName() const override { return "subfilereference"; }
-
-protected:
-	friend class Model;
-	LDSubfileReference (Model* model);
-	LDSubfileReference(LDDocument* reference, const Matrix& transformationMatrix, const Vertex& position, Model* model = nullptr);
-
-private:
-	LDDocument* m_fileInfo;
-};
-
-/*
- * Represents a single code-3 triangle in the LDraw code file.
- */
-class LDTriangle : public LDObject
-{
-public:
-	static constexpr LDObjectType SubclassType = LDObjectType::Triangle;
-
-	virtual LDObjectType type() const override
-	{
-		return SubclassType;
-	}
-
-	virtual QString asText() const override;
-	virtual void invert() override;
-	int triangleCount() const override;
-	int numVertices() const override { return 3; }
-	QString typeName() const override { return "triangle"; }
-
-protected:
-	friend class Model;
-	LDTriangle (Model* model);
-	LDTriangle (Vertex const& v1, Vertex const& v2, Vertex const& v3, Model* model = nullptr);
-};
-
-/*
- * Represents a single code-4 quadrilateral.
- */
-class LDQuadrilateral : public LDObject
-{
-public:
-	static constexpr LDObjectType SubclassType = LDObjectType::Quadrilateral;
-
-	virtual LDObjectType type() const override
-	{
-		return SubclassType;
-	}
-
-	QString asText() const override;
-	void invert() override;
-	int triangleCount() const override;
-	int numVertices() const override { return 4; }
-	QString typeName() const override { return "quad"; }
-
-protected:
-	friend class Model;
-	LDQuadrilateral (Model* model);
-	LDQuadrilateral (const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex& v4, Model* model = nullptr);
-};
-
-/*
- * Models a Bézier curve. It is stored as a special comment in the LDraw code file and can be inlined down into line segments.
- */
-class LDBezierCurve : public LDObject
-{
-public:
-	static constexpr LDObjectType SubclassType = LDObjectType::BezierCurve;
-
-	virtual LDObjectType type() const override
-	{
-		return SubclassType;
-	}
-
-	virtual QString asText() const override;
-	virtual void invert() override;
-	Vertex pointAt (qreal t) const;
-	void rasterize(Model& model, int segments);
-	QVector<LDPolygon> rasterizePolygons (int segments);
-	int numVertices() const override { return 4; }
-	LDColor defaultColor() const override { return EdgeColor; }
-	QString typeName() const override { return "beziercurve"; }
-
-protected:
-	friend class Model;
-	LDBezierCurve (Model* model);
-	LDBezierCurve (const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3, Model* model = nullptr);
-};
-
-enum
-{
-	LowResolution = 16,
-	HighResolution = 48
-};
-
-/*
- * Changes a property in a manner that emits the appropriate signal to notify that the object changed.
- */
-template<typename T>
-void LDObject::changeProperty(T* property, const T& value)
-{
-	if (*property != value)
-	{
-		QString before = asText();
-		*property = value;
-		emit codeChanged(before, asText());
-	}
-}
--- a/src/lddocument.h	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/lddocument.h	Tue Feb 14 14:59:26 2017 +0200
@@ -19,7 +19,7 @@
 #pragma once
 #include <QObject>
 #include "main.h"
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 #include "editHistory.h"
 #include "glShared.h"
 #include "model.h"
--- a/src/ldobjectiterator.h	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/ldobjectiterator.h	Tue Feb 14 14:59:26 2017 +0200
@@ -17,7 +17,7 @@
  */
 
 #pragma once
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 #include "lddocument.h"
 
 template<typename T>
--- a/src/linetypes/comment.h	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/linetypes/comment.h	Tue Feb 14 14:59:26 2017 +0200
@@ -17,7 +17,7 @@
  */
 
 #pragma once
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 
 /*
  * Represents a line type 0 comment in the LDraw model.
--- a/src/linetypes/edgeline.h	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/linetypes/edgeline.h	Tue Feb 14 14:59:26 2017 +0200
@@ -17,7 +17,7 @@
  */
 
 #pragma once
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 
 /*
  * Represents a single code-2 line in the LDraw code file.
--- a/src/linetypes/empty.h	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/linetypes/empty.h	Tue Feb 14 14:59:26 2017 +0200
@@ -17,7 +17,7 @@
  */
 
 #pragma once
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 
 /*
  * Represents an empty line in the LDraw code file.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/linetypes/modelobject.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -0,0 +1,825 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2017 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include "../documentmanager.h"
+#include "../linetypes/modelobject.h"
+#include "../lddocument.h"
+#include "../miscallenous.h"
+#include "../mainwindow.h"
+#include "../editHistory.h"
+#include "../canvas.h"
+#include "../colors.h"
+#include "../glcompiler.h"
+#include "edgeline.h"
+
+// List of all LDObjects
+QMap<qint32, LDObject*> g_allObjects;
+
+enum { MAX_LDOBJECT_IDS = (1 << 24) };
+
+#define LDOBJ_DEFAULT_CTOR(T,BASE) \
+	T :: T (Model* model) : \
+	    BASE {model} {}
+
+// =============================================================================
+// LDObject constructors
+//
+LDObject::LDObject (Model* model) :
+    m_isHidden {false},
+    m_isSelected {false},
+    _model {model},
+    m_coords {Origin}
+{
+	assert(_model != nullptr);
+
+	// Let's hope that nobody goes to create 17 million objects anytime soon...
+	static qint32 nextId = 1; // 0 shalt be null
+	if (nextId < MAX_LDOBJECT_IDS)
+		m_id = nextId++;
+	else
+		m_id = 0;
+
+	if (m_id != 0)
+		g_allObjects[m_id] = this;
+
+	m_randomColor = QColor::fromHsv (rand() % 360, rand() % 256, rand() % 96 + 128);
+}
+
+LDSubfileReference::LDSubfileReference (Model* model) :
+    LDMatrixObject (model) {}
+
+LDOBJ_DEFAULT_CTOR (LDError, LDObject)
+LDOBJ_DEFAULT_CTOR (LDTriangle, LDObject)
+LDOBJ_DEFAULT_CTOR (LDQuadrilateral, LDObject)
+LDOBJ_DEFAULT_CTOR (LDBfc, LDObject)
+LDOBJ_DEFAULT_CTOR (LDBezierCurve, LDObject)
+
+LDObject::~LDObject()
+{
+	// Delete the GL lists
+	if (g_win)
+		g_win->renderer()->forgetObject(this);
+
+	// Remove this object from the list of LDObjects
+	g_allObjects.erase(g_allObjects.find(id()));
+}
+
+// =============================================================================
+//
+QString LDSubfileReference::asText() const
+{
+	QString val = format ("1 %1 %2 ", color(), position());
+	val += transformationMatrix().toString();
+	val += ' ';
+	val += fileInfo()->name();
+	return val;
+}
+
+// =============================================================================
+//
+QString LDTriangle::asText() const
+{
+	QString val = format ("3 %1", color());
+
+	for (int i = 0; i < 3; ++i)
+		val += format (" %1", vertex (i));
+
+	return val;
+}
+
+// =============================================================================
+//
+QString LDQuadrilateral::asText() const
+{
+	QString val = format ("4 %1", color());
+
+	for (int i = 0; i < 4; ++i)
+		val += format (" %1", vertex (i));
+
+	return val;
+}
+
+QString LDBezierCurve::asText() const
+{
+	QString result = format ("0 !LDFORGE BEZIER_CURVE %1", color());
+
+	// Add the coordinates
+	for (int i = 0; i < 4; ++i)
+		result += format (" %1", vertex (i));
+
+	return result;
+}
+
+// =============================================================================
+//
+QString LDError::asText() const
+{
+	return contents();
+}
+
+// =============================================================================
+//
+QString LDBfc::asText() const
+{
+	return format ("0 BFC %1", statementToString());
+}
+
+// =============================================================================
+//
+// Swap this object with another.
+//
+void LDObject::swap (LDObject* other)
+{
+	if (model() == other->model())
+		model()->swapObjects (this, other);
+}
+
+int LDObject::triangleCount() const
+{
+	return 0;
+}
+
+int LDSubfileReference::triangleCount() const
+{
+	return fileInfo()->triangleCount();
+}
+
+int LDTriangle::triangleCount() const
+{
+	return 1;
+}
+
+int LDQuadrilateral::triangleCount() const
+{
+	return 2;
+}
+
+int LDObject::numVertices() const
+{
+	return 0;
+}
+
+// =============================================================================
+//
+LDTriangle::LDTriangle (const Vertex& v1, const Vertex& v2, const Vertex& v3, Model* model) :
+    LDObject {model}
+{
+	setVertex (0, v1);
+	setVertex (1, v2);
+	setVertex (2, v3);
+}
+
+// =============================================================================
+//
+LDQuadrilateral::LDQuadrilateral (const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex& v4, Model* model) :
+    LDObject {model}
+{
+	setVertex (0, v1);
+	setVertex (1, v2);
+	setVertex (2, v3);
+	setVertex (3, v4);
+}
+
+// =============================================================================
+//
+LDBezierCurve::LDBezierCurve(const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3, Model* model) :
+    LDObject {model}
+{
+	setVertex (0, v0);
+	setVertex (1, v1);
+	setVertex (2, v2);
+	setVertex (3, v3);
+}
+
+// =============================================================================
+//
+void LDObject::setDocument (Model* model)
+{
+	_model = model;
+}
+
+// =============================================================================
+//
+static void TransformObject (LDObject* obj, Matrix transform, Vertex pos, LDColor parentcolor)
+{
+	switch (obj->type())
+	{
+	case LDObjectType::EdgeLine:
+	case LDObjectType::ConditionalEdge:
+	case LDObjectType::Triangle:
+	case LDObjectType::Quadrilateral:
+		for (int i = 0; i < obj->numVertices(); ++i)
+		{
+			Vertex v = obj->vertex (i);
+			v.transform (transform, pos);
+			obj->setVertex (i, v);
+		}
+		break;
+
+	case LDObjectType::SubfileReference:
+		{
+			LDSubfileReference* ref = static_cast<LDSubfileReference*> (obj);
+			Matrix newMatrix = transform * ref->transformationMatrix();
+			Vertex newpos = ref->position();
+			newpos.transform (transform, pos);
+			ref->setPosition (newpos);
+			ref->setTransformationMatrix (newMatrix);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	if (obj->color() == MainColor)
+		obj->setColor (parentcolor);
+}
+
+// =============================================================================
+// -----------------------------------------------------------------------------
+void LDSubfileReference::inlineContents(Model& model, bool deep, bool render)
+{
+	Model inlined {this->model()->documentManager()};
+	fileInfo()->inlineContents(inlined, deep, render);
+
+	// Transform the objects
+	for (LDObject* object : inlined)
+		TransformObject(object, transformationMatrix(), position(), color());
+
+	model.merge(inlined);
+}
+
+// =============================================================================
+//
+LDPolygon* LDObject::getPolygon()
+{
+	LDObjectType ot = type();
+	int num = (ot == LDObjectType::EdgeLine)		? 2
+			: (ot == LDObjectType::Triangle)	? 3
+			: (ot == LDObjectType::Quadrilateral)		? 4
+			: (ot == LDObjectType::ConditionalEdge)	? 5
+			: 0;
+
+	if (num == 0)
+		return nullptr;
+
+	LDPolygon* data = new LDPolygon;
+	data->id = id();
+	data->num = num;
+	data->color = color().index();
+
+	for (int i = 0; i < data->numVertices(); ++i)
+		data->vertices[i] = vertex (i);
+
+	return data;
+}
+
+LDColor LDObject::defaultColor() const
+{
+	return MainColor;
+}
+
+bool LDObject::isColored() const
+{
+	return true;
+}
+
+bool LDObject::isScemantic() const
+{
+	return true;
+}
+
+bool LDObject::hasMatrix() const
+{
+	return false;
+}
+
+// =============================================================================
+//
+QList<LDPolygon> LDSubfileReference::inlinePolygons()
+{
+	QList<LDPolygon> data = fileInfo()->inlinePolygons();
+
+	for (LDPolygon& entry : data)
+	{
+		for (int i = 0; i < entry.numVertices(); ++i)
+			entry.vertices[i].transform (transformationMatrix(), position());
+	}
+
+	return data;
+}
+
+// =============================================================================
+//
+// Index (i.e. line number) of this object
+//
+int LDObject::lineNumber() const
+{
+	if (model())
+	{
+		for (int i = 0; i < model()->size(); ++i)
+		{
+			if (model()->getObject(i) == this)
+				return i;
+		}
+	}
+
+	return -1;
+}
+
+// =============================================================================
+//
+// Object after this in the current file
+//
+LDObject* LDObject::next() const
+{
+	return model()->getObject(lineNumber() + 1);
+}
+
+// =============================================================================
+//
+// Object prior to this in the current file
+//
+LDObject* LDObject::previous() const
+{
+	return model()->getObject(lineNumber() - 1);
+}
+
+// =============================================================================
+//
+// Is the previous object INVERTNEXT?
+//
+bool LDObject::previousIsInvertnext (LDBfc*& ptr)
+{
+	LDObject* prev = previous();
+
+	if (prev and prev->type() == LDObjectType::Bfc and static_cast<LDBfc*> (prev)->statement() == BfcStatement::InvertNext)
+	{
+		ptr = static_cast<LDBfc*> (prev);
+		return true;
+	}
+
+	return false;
+}
+
+// =============================================================================
+//
+// Moves this object using the given vertex as a movement List
+//
+void LDObject::move (Vertex vect)
+{
+	if (hasMatrix())
+	{
+		LDMatrixObject* mo = static_cast<LDMatrixObject*> (this);
+		mo->setPosition (mo->position() + vect);
+	}
+	else
+	{
+		for (int i = 0; i < numVertices(); ++i)
+			setVertex (i, vertex (i) + vect);
+	}
+}
+
+bool LDObject::isHidden() const
+{
+	return m_isHidden;
+}
+
+void LDObject::setHidden (bool value)
+{
+	m_isHidden = value;
+}
+
+bool LDObject::isSelected() const
+{
+	return m_isSelected;
+}
+
+qint32 LDObject::id() const
+{
+	return m_id;
+}
+
+LDColor LDObject::color() const
+{
+	return m_color;
+}
+
+QColor LDObject::randomColor() const
+{
+	return m_randomColor;
+}
+
+Model* LDObject::model() const
+{
+	return _model;
+}
+
+// =============================================================================
+//
+void LDObject::invert() {}
+void LDBfc::invert() {}
+void LDError::invert() {}
+
+// =============================================================================
+//
+void LDTriangle::invert()
+{
+	// Triangle goes 0 -> 1 -> 2, reversed: 0 -> 2 -> 1.
+	// Thus, we swap 1 and 2.
+	Vertex tmp = vertex (1);
+	setVertex (1, vertex (2));
+	setVertex (2, tmp);
+
+	return;
+}
+
+// =============================================================================
+//
+void LDQuadrilateral::invert()
+{
+	// Quad:     0 -> 1 -> 2 -> 3
+	// reversed: 0 -> 3 -> 2 -> 1
+	// Thus, we swap 1 and 3.
+	Vertex tmp = vertex (1);
+	setVertex (1, vertex (3));
+	setVertex (3, tmp);
+}
+
+// =============================================================================
+//
+void LDSubfileReference::invert()
+{
+	if (model() == nullptr)
+		return;
+
+	// Check whether subfile is flat
+	int axisSet = (1 << X) | (1 << Y) | (1 << Z);
+	Model model {this->model()->documentManager()};
+	fileInfo()->inlineContents(model, true, false);
+
+	for (LDObject* obj : model.objects())
+	{
+		for (int i = 0; i < obj->numVertices(); ++i)
+		{
+			Vertex const& vrt = obj->vertex (i);
+
+			if (axisSet & (1 << X) and vrt.x() != 0.0)
+				axisSet &= ~(1 << X);
+
+			if (axisSet & (1 << Y) and vrt.y() != 0.0)
+				axisSet &= ~(1 << Y);
+
+			if (axisSet & (1 << Z) and vrt.z() != 0.0)
+				axisSet &= ~(1 << Z);
+		}
+
+		if (axisSet == 0)
+			break;
+	}
+
+	if (axisSet != 0)
+	{
+		// Subfile has all vertices zero on one specific plane, so it is flat.
+		// Let's flip it.
+		Matrix matrixModifier = Matrix::identity;
+
+		if (axisSet & (1 << X))
+			matrixModifier(0, 0) = -1;
+
+		if (axisSet & (1 << Y))
+			matrixModifier(1, 1) = -1;
+
+		if (axisSet & (1 << Z))
+			matrixModifier(2, 2) = -1;
+
+		setTransformationMatrix (transformationMatrix() * matrixModifier);
+		return;
+	}
+
+	// Subfile is not flat. Resort to invertnext.
+	int idx = lineNumber();
+
+	if (idx > 0)
+	{
+		LDBfc* bfc = dynamic_cast<LDBfc*> (previous());
+
+		if (bfc and bfc->statement() == BfcStatement::InvertNext)
+		{
+			// This is prefixed with an invertnext, thus remove it.
+			this->model()->remove(bfc);
+			return;
+		}
+	}
+
+	// Not inverted, thus prefix it with a new invertnext.
+	this->model()->emplaceAt<LDBfc>(idx, BfcStatement::InvertNext);
+}
+
+// =============================================================================
+//
+void LDBezierCurve::invert()
+{
+	// A Bézier curve's control points probably need to be, though.
+	Vertex tmp = vertex (1);
+	setVertex (1, vertex (0));
+	setVertex (0, tmp);
+	tmp = vertex (3);
+	setVertex (3, vertex (2));
+	setVertex (2, tmp);
+}
+
+// =============================================================================
+//
+LDObject* LDObject::fromID(qint32 id)
+{
+	return g_allObjects.value(id);
+}
+
+// =============================================================================
+//
+void LDObject::setColor (LDColor color)
+{
+	changeProperty(&m_color, color);
+}
+
+// =============================================================================
+//
+// Get a vertex by index
+//
+const Vertex& LDObject::vertex (int i) const
+{
+	return m_coords[i];
+}
+
+// =============================================================================
+//
+// Set a vertex to the given value
+//
+void LDObject::setVertex (int i, const Vertex& vert)
+{
+	changeProperty(&m_coords[i], vert);
+}
+
+LDMatrixObject::LDMatrixObject (Model* model) :
+    LDObject (model),
+	m_position (Origin) {}
+
+LDMatrixObject::LDMatrixObject (const Matrix& transform, const Vertex& pos, Model* model) :
+    LDObject (model),
+	m_position (pos),
+	m_transformationMatrix (transform) {}
+
+void LDMatrixObject::setCoordinate (const Axis ax, double value)
+{
+	Vertex v = position();
+
+	switch (ax)
+	{
+		case X: v.setX (value); break;
+		case Y: v.setY (value); break;
+		case Z: v.setZ (value); break;
+	}
+
+	setPosition (v);
+}
+
+const Vertex& LDMatrixObject::position() const
+{
+	return m_position;
+}
+
+// =============================================================================
+//
+void LDMatrixObject::setPosition (const Vertex& a)
+{
+	changeProperty(&m_position, a);
+}
+
+// =============================================================================
+//
+const Matrix& LDMatrixObject::transformationMatrix() const
+{
+	return m_transformationMatrix;
+}
+
+void LDMatrixObject::setTransformationMatrix (const Matrix& val)
+{
+	changeProperty(&m_transformationMatrix, val);
+}
+
+LDError::LDError (QString contents, QString reason, Model* model) :
+    LDObject (model),
+	m_contents (contents),
+	m_reason (reason) {}
+
+QString LDError::reason() const
+{
+	return m_reason;
+}
+
+QString LDError::contents() const
+{
+	return m_contents;
+}
+
+QString LDError::fileReferenced() const
+{
+	return m_fileReferenced;
+}
+
+void LDError::setFileReferenced (QString value)
+{
+	m_fileReferenced = value;
+}
+
+LDBfc::LDBfc (const BfcStatement type, Model* model) :
+    LDObject {model},
+    m_statement {type} {}
+
+BfcStatement LDBfc::statement() const
+{
+	return m_statement;
+}
+
+void LDBfc::setStatement (BfcStatement value)
+{
+	m_statement = value;
+}
+
+QString LDBfc::statementToString() const
+{
+	return LDBfc::statementToString (statement());
+}
+
+QString LDBfc::statementToString (BfcStatement statement)
+{
+	static const char* statementStrings[] =
+	{
+		"CERTIFY CCW",
+		"CCW",
+		"CERTIFY CW",
+		"CW",
+		"NOCERTIFY",
+		"INVERTNEXT",
+		"CLIP",
+		"CLIP CCW",
+		"CLIP CW",
+		"NOCLIP",
+	};
+
+	if ((int) statement >= 0 and (int) statement < countof (statementStrings))
+		return QString::fromLatin1 (statementStrings[(int) statement]);
+	else
+		return "";
+}
+
+Vertex LDBezierCurve::pointAt (qreal t) const
+{
+	if (t >= 0.0 and t <= 1.0)
+	{
+		Vertex result;
+		result += pow (1.0 - t, 3) * vertex (0);
+		result += (3 * pow (1.0 - t, 2) * t) * vertex (2);
+		result += (3 * (1.0 - t) * pow (t, 2)) * vertex (3);
+		result += pow (t, 3) * vertex (1);
+		return result;
+	}
+	else
+		return Vertex();
+}
+
+void LDBezierCurve::rasterize(Model& model, int segments)
+{
+	QVector<LDPolygon> polygons = rasterizePolygons(segments);
+
+	for (LDPolygon& poly : polygons)
+	{
+		LDEdgeLine* line = model.emplace<LDEdgeLine>(poly.vertices[0], poly.vertices[1]);
+		line->setColor (poly.color);
+	}
+}
+
+QVector<LDPolygon> LDBezierCurve::rasterizePolygons(int segments)
+{
+	QVector<LDPolygon> result;
+	QVector<Vertex> parms;
+	parms.append (pointAt (0.0));
+
+	for (int i = 1; i < segments; ++i)
+		parms.append (pointAt (double (i) / segments));
+
+	parms.append (pointAt (1.0));
+	LDPolygon poly;
+	poly.color = color().index();
+	poly.id = id();
+	poly.num = 2;
+
+	for (int i = 0; i < segments; ++i)
+	{
+		poly.vertices[0] = parms[i];
+		poly.vertices[1] = parms[i + 1];
+		result << poly;
+	}
+
+	return result;
+}
+
+LDSubfileReference::LDSubfileReference(LDDocument* reference, const Matrix& transformationMatrix,
+                                       const Vertex& position, Model* model) :
+    LDMatrixObject {transformationMatrix, position, model},
+    m_fileInfo {reference} {}
+
+// =============================================================================
+//
+LDDocument* LDSubfileReference::fileInfo() const
+{
+	return m_fileInfo;
+}
+
+void LDSubfileReference::setFileInfo (LDDocument* newReferee)
+{
+	changeProperty(&m_fileInfo, newReferee);
+
+	if (model())
+		model()->recountTriangles();
+
+	// If it's an immediate subfile reference (i.e. this subfile is in an opened document), we need to pre-compile the
+	// GL polygons for the document if they don't exist already.
+	if (newReferee and
+		newReferee->isFrozen() == false and
+		newReferee->polygonData().isEmpty())
+	{
+		newReferee->initializeCachedData();
+	}
+}
+
+void LDObject::getVertices (QSet<Vertex>& verts) const
+{
+	for (int i = 0; i < numVertices(); ++i)
+		verts.insert(vertex(i));
+}
+
+void LDSubfileReference::getVertices (QSet<Vertex>& verts) const
+{
+	verts.unite(fileInfo()->inlineVertices());
+}
+
+QString LDObject::objectListText() const
+{
+	if (numVertices() > 0)
+	{
+		QString result;
+
+		for (int i = 0; i < numVertices(); ++i)
+		{
+			if (i != 0)
+				result += ", ";
+
+			result += vertex(i).toString (true);
+		}
+
+		return result;
+	}
+	else
+	{
+		return typeName();
+	}
+}
+
+QString LDError::objectListText() const
+{
+	return "ERROR: " + asText();
+}
+
+QString LDSubfileReference::objectListText() const
+{
+	QString result = format ("%1 %2, (", fileInfo()->getDisplayName(), position().toString(true));
+
+	for (int i = 0; i < 9; ++i)
+		result += format("%1%2", transformationMatrix().value(i), (i != 8) ? " " : "");
+
+	result += ')';
+	return result;
+}
+
+QString LDBfc::objectListText() const
+{
+	return statementToString();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/linetypes/modelobject.h	Tue Feb 14 14:59:26 2017 +0200
@@ -0,0 +1,351 @@
+/*
+ *  LDForge: LDraw parts authoring CAD
+ *  Copyright (C) 2013 - 2017 Teemu Piippo
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+#include <type_traits>
+#include "../main.h"
+#include "../basics.h"
+#include "../glShared.h"
+#include "../colors.h"
+
+class Model;
+class LDDocument;
+
+/*
+ * Object type codes.
+ */
+enum LDObjectType
+{
+	SubfileReference,	//	Object represents a	sub-file reference
+	Quadrilateral,		//	Object represents a	quadrilateral
+	Triangle,			//	Object represents a	triangle
+	EdgeLine,			//	Object represents a	line
+	ConditionalEdge,	//	Object represents a	conditional line
+	Bfc,				//	Object represents a	BFC statement
+	Comment,			//	Object represents a	comment
+	Error,				//	Object is the result of failed parsing
+	Empty,				//	Object represents an empty line
+	BezierCurve,		//	Object represents a Bézier curve
+	_End
+};
+
+MAKE_ITERABLE_ENUM(LDObjectType)
+
+/*
+ * Represents one line of code in an LDraw model file.
+ */
+class LDObject : public QObject
+{
+	Q_OBJECT
+
+public:
+	virtual QString asText() const = 0; // This object as LDraw code
+	LDColor color() const;
+	virtual LDColor defaultColor() const; // What color does the object default to?
+	Model* model() const;
+	LDPolygon* getPolygon();
+	virtual void getVertices (QSet<Vertex>& verts) const;
+	virtual bool hasMatrix() const; // Does this object have a matrix and position? (see LDMatrixObject)
+	qint32 id() const;
+	virtual void invert(); // Inverts this object (winding is reversed)
+	virtual bool isColored() const;
+	bool isHidden() const;
+	virtual bool isScemantic() const; // Does this object have meaning in the part model?
+	bool isSelected() const;
+	int lineNumber() const;
+	void move (Vertex vect);
+	LDObject* next() const;
+	virtual int numVertices() const;
+	virtual QString objectListText() const;
+	LDObject* previous() const;
+	bool previousIsInvertnext(class LDBfc*& ptr);
+	QColor randomColor() const;
+	void setColor (LDColor color);
+	void setHidden (bool value);
+	void setVertex (int i, const Vertex& vert);
+	void swap (LDObject* other);
+	virtual int triangleCount() const;
+	virtual LDObjectType type() const = 0;
+	virtual QString typeName() const = 0;
+	const Vertex& vertex (int i) const;
+
+	static LDObject* fromID(qint32 id);
+
+signals:
+	void codeChanged(QString before, QString after);
+
+protected:
+	friend class Model;
+	LDObject (Model* model = nullptr);
+	virtual ~LDObject();
+	void setDocument(Model* model);
+
+	template<typename T>
+	void changeProperty(T* property, const T& value);
+
+private:
+	bool m_isHidden;
+	bool m_isSelected;
+	Model* _model;
+	qint32 m_id;
+	LDColor m_color;
+	QColor m_randomColor;
+	Vertex m_coords[4];
+};
+
+/*
+ * Base class for objects with matrices.
+ */
+class LDMatrixObject : public LDObject
+{
+	Vertex m_position;
+
+public:
+	const Vertex& position() const;
+	void setCoordinate (const Axis ax, double value);
+	void setPosition (const Vertex& a);
+	void setTransformationMatrix (const Matrix& value);
+	const Matrix& transformationMatrix() const;
+
+protected:
+	LDMatrixObject (Model* model = nullptr);
+	LDMatrixObject (const Matrix& transformationMatrix, const Vertex& pos, Model* model = nullptr);
+
+private:
+	Matrix m_transformationMatrix;
+};
+
+/*
+ * Represents a line in the LDraw file that could not be properly parsed.
+ */
+class LDError : public LDObject
+{
+public:
+	static constexpr LDObjectType SubclassType = LDObjectType::Error;
+
+	virtual LDObjectType type() const override
+	{
+		return SubclassType;
+	}
+
+	virtual QString asText() const override;
+	virtual void invert() override;
+	QString reason() const;
+	QString contents() const;
+	QString fileReferenced() const;
+	void setFileReferenced (QString value);
+	QString objectListText() const override;
+	bool isColored() const override { return false; }
+	QString typeName() const override { return "error"; }
+
+protected:
+	friend class Model;
+	LDError (Model* model);
+	LDError (QString contents, QString reason, Model* model = nullptr);
+
+private:
+	QString m_fileReferenced; // If this error was caused by inability to open a file, what file was that?
+	QString m_contents; // The LDraw code that was being parsed
+	QString m_reason;
+};
+
+/*
+ * Represents a 0 BFC statement in the LDraw code.
+ */
+enum class BfcStatement
+{
+	CertifyCCW,
+	CCW,
+	CertifyCW,
+	CW,
+	NoCertify,
+	InvertNext,
+	Clip,
+	ClipCCW,
+	ClipCW,
+	NoClip,
+	_End
+};
+
+MAKE_ITERABLE_ENUM(BfcStatement)
+
+class LDBfc : public LDObject
+{
+	public:
+	static constexpr LDObjectType SubclassType = LDObjectType::Bfc;
+
+	virtual LDObjectType type() const override
+	{
+		return SubclassType;
+	}
+
+	virtual QString asText() const override;
+	virtual void invert() override;
+protected:
+	friend class Model;
+	LDBfc (Model* model);
+
+public:
+	bool isScemantic() const override { return statement() == BfcStatement::InvertNext; }
+    QString objectListText() const override;
+	BfcStatement statement() const;
+	void setStatement (BfcStatement value);
+	QString statementToString() const;
+	bool isColored() const override { return false; }
+	QString typeName() const override { return "bfc"; }
+
+	static QString statementToString (BfcStatement statement);
+
+protected:
+	LDBfc (const BfcStatement type, Model* model = nullptr);
+
+private:
+	BfcStatement m_statement;
+};
+
+/*
+ * Represents a single code-1 subfile reference.
+ */
+class LDSubfileReference : public LDMatrixObject
+{
+public:
+	static constexpr LDObjectType SubclassType = LDObjectType::SubfileReference;
+
+	virtual LDObjectType type() const override
+	{
+		return SubclassType;
+	}
+
+	virtual QString asText() const override;
+	virtual void invert() override;
+	LDDocument* fileInfo() const;
+	virtual void getVertices (QSet<Vertex>& verts) const override;
+	void inlineContents(Model& model, bool deep, bool render);
+	QList<LDPolygon> inlinePolygons();
+	QString objectListText() const override;
+	void setFileInfo (LDDocument* fileInfo);
+	int triangleCount() const override;
+	bool hasMatrix() const override { return true; }
+	QString typeName() const override { return "subfilereference"; }
+
+protected:
+	friend class Model;
+	LDSubfileReference (Model* model);
+	LDSubfileReference(LDDocument* reference, const Matrix& transformationMatrix, const Vertex& position, Model* model = nullptr);
+
+private:
+	LDDocument* m_fileInfo;
+};
+
+/*
+ * Represents a single code-3 triangle in the LDraw code file.
+ */
+class LDTriangle : public LDObject
+{
+public:
+	static constexpr LDObjectType SubclassType = LDObjectType::Triangle;
+
+	virtual LDObjectType type() const override
+	{
+		return SubclassType;
+	}
+
+	virtual QString asText() const override;
+	virtual void invert() override;
+	int triangleCount() const override;
+	int numVertices() const override { return 3; }
+	QString typeName() const override { return "triangle"; }
+
+protected:
+	friend class Model;
+	LDTriangle (Model* model);
+	LDTriangle (Vertex const& v1, Vertex const& v2, Vertex const& v3, Model* model = nullptr);
+};
+
+/*
+ * Represents a single code-4 quadrilateral.
+ */
+class LDQuadrilateral : public LDObject
+{
+public:
+	static constexpr LDObjectType SubclassType = LDObjectType::Quadrilateral;
+
+	virtual LDObjectType type() const override
+	{
+		return SubclassType;
+	}
+
+	QString asText() const override;
+	void invert() override;
+	int triangleCount() const override;
+	int numVertices() const override { return 4; }
+	QString typeName() const override { return "quad"; }
+
+protected:
+	friend class Model;
+	LDQuadrilateral (Model* model);
+	LDQuadrilateral (const Vertex& v1, const Vertex& v2, const Vertex& v3, const Vertex& v4, Model* model = nullptr);
+};
+
+/*
+ * Models a Bézier curve. It is stored as a special comment in the LDraw code file and can be inlined down into line segments.
+ */
+class LDBezierCurve : public LDObject
+{
+public:
+	static constexpr LDObjectType SubclassType = LDObjectType::BezierCurve;
+
+	virtual LDObjectType type() const override
+	{
+		return SubclassType;
+	}
+
+	virtual QString asText() const override;
+	virtual void invert() override;
+	Vertex pointAt (qreal t) const;
+	void rasterize(Model& model, int segments);
+	QVector<LDPolygon> rasterizePolygons (int segments);
+	int numVertices() const override { return 4; }
+	LDColor defaultColor() const override { return EdgeColor; }
+	QString typeName() const override { return "beziercurve"; }
+
+protected:
+	friend class Model;
+	LDBezierCurve (Model* model);
+	LDBezierCurve (const Vertex& v0, const Vertex& v1, const Vertex& v2, const Vertex& v3, Model* model = nullptr);
+};
+
+enum
+{
+	LowResolution = 16,
+	HighResolution = 48
+};
+
+/*
+ * Changes a property in a manner that emits the appropriate signal to notify that the object changed.
+ */
+template<typename T>
+void LDObject::changeProperty(T* property, const T& value)
+{
+	if (*property != value)
+	{
+		QString before = asText();
+		*property = value;
+		emit codeChanged(before, asText());
+	}
+}
--- a/src/mainwindow.h	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/mainwindow.h	Tue Feb 14 14:59:26 2017 +0200
@@ -24,7 +24,7 @@
 #include <QRadioButton>
 #include <QTreeWidget>
 #include <QMetaMethod>
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 #include "colors.h"
 #include "doublemap.h"
 
--- a/src/mathfunctions.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/mathfunctions.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -17,7 +17,7 @@
  */
 
 #include "mathfunctions.h"
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 #include "miscallenous.h"
 
 
--- a/src/model.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/model.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -17,7 +17,7 @@
  */
 
 #include "model.h"
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 #include "documentmanager.h"
 #include "linetypes/comment.h"
 #include "linetypes/conditionaledge.h"
--- a/src/model.h	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/model.h	Tue Feb 14 14:59:26 2017 +0200
@@ -18,7 +18,7 @@
 
 #pragma once
 #include "main.h"
-#include "ldObject.h"
+#include "linetypes/modelobject.h"
 
 /*
  * This class represents a LDraw model, consisting of a vector of objects. It manages LDObject ownership.
--- a/src/toolsets/basictoolset.cpp	Tue Feb 14 14:53:06 2017 +0200
+++ b/src/toolsets/basictoolset.cpp	Tue Feb 14 14:59:26 2017 +0200
@@ -24,7 +24,7 @@
 #include <QVBoxLayout>
 #include "../canvas.h"
 #include "../lddocument.h"
-#include "../ldObject.h"
+#include "../linetypes/modelobject.h"
 #include "../ldobjectiterator.h"
 #include "../mainwindow.h"
 #include "../dialogs/colorselector.h"

mercurial