- Add editors for string and bool properties

Tue, 15 Mar 2022 18:52:48 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Tue, 15 Mar 2022 18:52:48 +0200
changeset 183
97b591813c8b
parent 182
27fb1c3c9fbb
child 184
35bbfad4d0f4

- Add editors for string and bool properties
- Add invert action

CMakeLists.txt file | annotate | diff | comparison | revisions
icons/invert.png file | annotate | diff | comparison | revisions
ldforge.qrc file | annotate | diff | comparison | revisions
src/invert.cpp file | annotate | diff | comparison | revisions
src/invert.h file | annotate | diff | comparison | revisions
src/ldrawalgorithm.cpp file | annotate | diff | comparison | revisions
src/ldrawalgorithm.h file | annotate | diff | comparison | revisions
src/linetypes/compoundobject.cpp file | annotate | diff | comparison | revisions
src/linetypes/compoundobject.h file | annotate | diff | comparison | revisions
src/linetypes/object.h file | annotate | diff | comparison | revisions
src/linetypes/quadrilateral.cpp file | annotate | diff | comparison | revisions
src/linetypes/quadrilateral.h file | annotate | diff | comparison | revisions
src/linetypes/subfilereference.cpp file | annotate | diff | comparison | revisions
src/linetypes/subfilereference.h file | annotate | diff | comparison | revisions
src/linetypes/triangle.cpp file | annotate | diff | comparison | revisions
src/linetypes/triangle.h file | annotate | diff | comparison | revisions
src/mainwindow.cpp file | annotate | diff | comparison | revisions
src/mainwindow.h file | annotate | diff | comparison | revisions
src/mainwindow.ui file | annotate | diff | comparison | revisions
src/parser.cpp file | annotate | diff | comparison | revisions
src/polygoncache.cpp file | annotate | diff | comparison | revisions
src/polygoncache.h file | annotate | diff | comparison | revisions
src/ui/objecteditor.cpp file | annotate | diff | comparison | revisions
src/ui/objecteditor.h file | annotate | diff | comparison | revisions
--- a/CMakeLists.txt	Sun Mar 13 20:26:28 2022 +0200
+++ b/CMakeLists.txt	Tue Mar 15 18:52:48 2022 +0200
@@ -54,6 +54,7 @@
 	src/gl/gridprogram.cpp
 	src/gl/partrenderer.cpp
 	src/gl/vertexprogram.cpp
+	src/linetypes/compoundobject.cpp
 	src/linetypes/conditionaledge.cpp
 	src/linetypes/edge.cpp
 	src/linetypes/errorline.cpp
@@ -111,6 +112,7 @@
 	src/gl/gridprogram.h
 	src/gl/partrenderer.h
 	src/gl/vertexprogram.h
+	src/linetypes/compoundobject.h
 	src/linetypes/conditionaledge.h
 	src/linetypes/edge.h
 	src/linetypes/errorline.h
Binary file icons/invert.png has changed
--- a/ldforge.qrc	Sun Mar 13 20:26:28 2022 +0200
+++ b/ldforge.qrc	Tue Mar 15 18:52:48 2022 +0200
@@ -29,5 +29,6 @@
         <file>icons/navigate-outline.png</file>
         <file>icons/trash-bin-outline.png</file>
         <file>icons/axes.png</file>
+        <file>icons/invert.png</file>
     </qresource>
 </RCC>
--- a/src/invert.cpp	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/invert.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -20,54 +20,8 @@
 #include "model.h"
 #include "gl/common.h"
 #include "invert.h"
-
-#if 0
-/*
- * Returns whether or not the document is flat.
- * If it is flat, the result is stored in *axis.
- */
-bool isflat(Model* model, Axis* flatDimension)
-{
-	// The dimensions that this model is potentially flat in.
-	QVector<Axis> dimensions = {X, Y, Z};
-
-	// Iterate through everything in the subfile. If there is any vertex with a coordinate not at
-	// zero, the subfile is not flat in that dimension.
-	for (LDObject* subfileObject : model->objects())
-	{
-		for (int i = 0; i < subfileObject->numVertices(); ++i)
-		{
-			Vertex const& v_i = subfileObject->vertex(i);
-
-			if (not qFuzzyCompare(v_i.x, 0.0))
-				dimensions.removeOne(X);
-
-			if (not qFuzzyCompare(v_i.y, 0.0))
-				dimensions.removeOne(Y);
-
-			if (not qFuzzyCompare(v_i.z, 0.0))
-				dimensions.removeOne(Z);
-		}
-
-		// If there are no more dimensions left, we can exit the loop.
-		if (dimensions.isEmpty())
-			break;
-	}
-
-	if (dimensions.size() == 1)
-	{
-		// The model is flat in one dimension, return that.
-		// If the model is flat in two or three dimensions, it's not really a valid model.
-		*flatDimension = dimensions[0];
-		return true;
-	}
-	else
-	{
-		// The model is not flat.
-		return false;
-	}
-}
-#endif
+#include "documentmanager.h"
+#include "modeleditor.h"
 
 /*
  * Returns a matrix that causes a flip on the given dimension.
@@ -80,56 +34,6 @@
 	return result;
 }
 
-#if 0
-/*
- * Inverts an LDObject so that its winding is changed.
- */
-void invert(LDObject* obj, DocumentManager* context)
-{
-	if (obj->numPolygonVertices() > 0)
-	{
-		// Object is vertex based, so change the order of the vertices.
-		QVector<Vertex> vertices;
-		vertices.resize(obj->numPolygonVertices());
-
-		for (int i = 0; i < vertices.size(); i += 1)
-			vertices[vertices.size() - 1 - i] = obj->vertex(i);
-
-		for (int i = 0; i < vertices.size(); i += 1)
-			obj->setVertex(i, vertices[i]);
-	}
-	else if (obj->type() == LDObjectType::SubfileReference)
-	{
-		// Check whether subfile is flat. If it is, flip it on the axis on which it is flat.
-		Model model {context};
-		LDSubfileReference* reference = static_cast<LDSubfileReference*>(obj);
-		reference->fileInfo(context)->inlineContents(model, true, false);
-		Axis flatDimension;
-
-		if (::isflat(&model, &flatDimension))
-		{
-			reference->setTransformationMatrix(
-				reference->transformationMatrix() * ::flipmatrix(flatDimension)
-			);
-		}
-		else
-		{
-			// Subfile is not flat. Resort to invertnext.
-			reference->setInverted(not reference->isInverted());
-		}
-	}
-	else if (obj->type() == LDObjectType::CircularPrimitive)
-	{
-		auto primitive = static_cast<LDCircularPrimitive*>(obj);
-
-		if (primitive->isFlat())
-			primitive->setTransformationMatrix(primitive->transformationMatrix() * ::flipmatrix(Y));
-		else
-			primitive->setInverted(not primitive->isInverted());
-	}
-}
-#endif
-
 /*
  * Inverts the winding of a polygon.
  */
--- a/src/invert.h	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/invert.h	Tue Mar 15 18:52:48 2022 +0200
@@ -20,8 +20,6 @@
 #include "main.h"
 #include "gl/common.h"
 
-bool isflat(class Model* model, Axis* axis);
-
 namespace math
 {
 	glm::mat4 flipmatrix(Axis dimension);
--- a/src/ldrawalgorithm.cpp	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/ldrawalgorithm.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -2,10 +2,10 @@
 #include "linetypes/quadrilateral.h"
 #include "linetypes/triangle.h"
 
-void ldraw::invert(ModelEditor& editor, ldraw::id_t id)
+void ldraw::invert(ModelEditor& editor, ldraw::id_t id, GetPolygonsContext* context)
 {
-	editor.modifyObject(id, [](ldraw::Object* object){
-		object->invert();
+	editor.modifyObject(id, [context](ldraw::Object* object){
+		object->invert(context);
 	});
 }
 
--- a/src/ldrawalgorithm.h	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/ldrawalgorithm.h	Tue Mar 15 18:52:48 2022 +0200
@@ -17,6 +17,6 @@
 		Diagonal splitType = Diagonal::Diagonal_13
 	) -> std::optional<std::pair<triangleid_t, triangleid_t>>;
 
-	void invert(ModelEditor& editor, ldraw::id_t id);
+	void invert(ModelEditor& editor, ldraw::id_t id, GetPolygonsContext *context);
 	void makeUnofficial(ModelEditor &editor);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/linetypes/compoundobject.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -0,0 +1,115 @@
+#include "compoundobject.h"
+#include "documentmanager.h"
+#include "invert.h"
+#include "polygoncache.h"
+
+ldraw::CompoundObject::CompoundObject
+(
+	const glm::mat4& transformation,
+	const Color color
+) :
+	ColoredObject{color},
+	transformation{transformation}
+{
+}
+
+QVariant ldraw::CompoundObject::getProperty(Property property) const
+{
+	switch (property)
+	{
+	case Property::Transformation:
+		return QVariant::fromValue(this->transformation);
+	case Property::IsInverted:
+		return this->isInverted;
+	default:
+		return ColoredObject::getProperty(property);
+	}
+}
+
+void ldraw::CompoundObject::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair)
+{
+	LDRAW_OBJECT_HANDLE_SET_PROPERTY(Transformation, {this->transformation = value;});
+	LDRAW_OBJECT_HANDLE_SET_PROPERTY(IsInverted, {this->isInverted = value;});
+	ldraw::ColoredObject::setProperty(result, pair);
+}
+
+glm::vec3 ldraw::CompoundObject::position() const
+{
+	return this->transformation[3];
+}
+
+void ldraw::CompoundObject::invert(GetPolygonsContext *context)
+{
+	const std::optional<Axis> flatDimension = context ? this->flatDimension(context) : std::optional<Axis>{};
+	if (flatDimension.has_value())
+	{
+		glm::mat4 matrix = glm::identity<glm::mat4>();
+		matrix[*flatDimension][*flatDimension] = -1.0f;
+		this->transformation *= matrix;
+	}
+	else
+	{
+		this->isInverted = not this->isInverted;
+	}
+}
+
+
+QDataStream& ldraw::CompoundObject::serialize(QDataStream &stream) const
+{
+	return ColoredObject::serialize(stream) << this->transformation << this->isInverted;
+}
+
+QDataStream& ldraw::CompoundObject::deserialize(QDataStream &stream)
+{
+	return ColoredObject::deserialize(stream) >> this->transformation >> this->isInverted;
+}
+
+/**
+ * @brief Finds out in which dimension the object is flat in. In that dimension all vertices have a value of 0.
+ * If the object is not flat, this does not return a value.
+ * @param model Model to find out flatness of
+ * @param documents Where to look for subfiles
+ * @returns dimension the model is flat in, if such dimension exists, no value otherwise.
+ */
+std::optional<Axis> ldraw::CompoundObject::flatDimension(GetPolygonsContext *context) const
+{
+	// The dimensions that this model is potentially flat in.
+	QVector<Axis> dimensions = {X, Y, Z};
+	std::vector<gl::Polygon> polygons;
+	this->getPolygons(polygons, context);
+	for (const gl::Polygon& polygon : polygons)
+	{
+		for (unsigned int i = 0; i < polygon.numPolygonVertices(); i += 1)
+		{
+			const glm::vec3& v_i = polygon.vertices[i];
+			if (not qFuzzyCompare(v_i.x, 0.0f))
+			{
+				dimensions.removeOne(X);
+			}
+			if (not qFuzzyCompare(v_i.y, 0.0f))
+			{
+				dimensions.removeOne(Y);
+			}
+			if (not qFuzzyCompare(v_i.z, 0.0f))
+			{
+				dimensions.removeOne(Z);
+			}
+		}
+		// If there are no more dimensions left, we can exit the loop.
+		if (dimensions.isEmpty())
+		{
+			break;
+		}
+	}
+	if (dimensions.size() == 1)
+	{
+		// The model is flat in one dimension, return that.
+		// If the model is flat in two or three dimensions, it's not really a valid model.
+		return dimensions[0];
+	}
+	else
+	{
+		// The model is not flat.
+		return {};
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/linetypes/compoundobject.h	Tue Mar 15 18:52:48 2022 +0200
@@ -0,0 +1,33 @@
+#pragma once
+#include "object.h"
+
+class Model;
+
+namespace ldraw
+{
+	class CompoundObject;
+}
+
+/**
+ * @brief An abstract object that has a transformation mmatrix and can be inverted.
+ * It can be inlined into multiple objects.
+ */
+class ldraw::CompoundObject : public ColoredObject
+{
+public:
+	CompoundObject() = default;
+	CompoundObject(
+		const glm::mat4& transformation,
+		const Color color = ldraw::MAIN_COLOR);
+	QVariant getProperty(Property property) const override;
+	glm::vec3 position() const;
+	void invert(GetPolygonsContext*context) override;
+	Model* resolve(const ModelId callingModelId, DocumentManager* documents) const;
+	QDataStream& serialize(QDataStream& stream) const override;
+	QDataStream& deserialize(QDataStream& stream) override;
+	std::optional<Axis> flatDimension(GetPolygonsContext *context) const;
+	glm::mat4 transformation;
+	bool isInverted = false;
+protected:
+	void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override;
+};
--- a/src/linetypes/object.h	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/linetypes/object.h	Tue Mar 15 18:52:48 2022 +0200
@@ -72,7 +72,7 @@
 	virtual QBrush textRepresentationBackground() const;
 	virtual QFont textRepresentationFont() const;
 	virtual void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const;
-	virtual void invert() {}
+	virtual void invert(GetPolygonsContext*) {}
 	virtual int numPoints() const { return 0; }
 	virtual const glm::vec3& getPoint(int index) const;
 	virtual QDataStream& serialize(QDataStream& stream) const;
--- a/src/linetypes/quadrilateral.cpp	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/linetypes/quadrilateral.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -23,7 +23,7 @@
 		this->id));
 }
 
-void ldraw::Quadrilateral::invert()
+void ldraw::Quadrilateral::invert(GetPolygonsContext *)
 {
 	//    0 1 2 3
 	// -> 2 1 0 3
--- a/src/linetypes/quadrilateral.h	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/linetypes/quadrilateral.h	Tue Mar 15 18:52:48 2022 +0200
@@ -12,7 +12,7 @@
 	using PolygonObject<4>::PolygonObject;
 	QString textRepresentation() const override;
 	void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override;
-	void invert() override;
+	void invert(GetPolygonsContext *) override;
 	Type typeIdentifier() const override;
 	QString toLDrawCode() const override;
 	QString iconName() const override;
--- a/src/linetypes/subfilereference.cpp	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/linetypes/subfilereference.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -9,8 +9,7 @@
 	const QString& referenceName,
 	const Color color
 ) :
-	ColoredObject{color},
-	transformation{transformation},
+	CompoundObject{transformation, color},
 	referenceName{referenceName}
 {
 }
@@ -19,20 +18,17 @@
 {
 	switch (property)
 	{
-	case Property::Transformation:
-		return QVariant::fromValue(this->transformation);
 	case Property::ReferenceName:
 		return this->referenceName;
 	default:
-		return ColoredObject::getProperty(property);
+		return CompoundObject::getProperty(property);
 	}
 }
 
 void ldraw::SubfileReference::setProperty(SetPropertyResult* result, const PropertyKeyValue& pair)
 {
-	LDRAW_OBJECT_HANDLE_SET_PROPERTY(Transformation, {this->transformation = value;});
 	LDRAW_OBJECT_HANDLE_SET_PROPERTY(ReferenceName, {this->referenceName = value;});
-	ldraw::ColoredObject::setProperty(result, pair);
+	ldraw::CompoundObject::setProperty(result, pair);
 }
 
 QString ldraw::SubfileReference::textRepresentation() const
@@ -83,16 +79,6 @@
 	}
 }
 
-glm::vec3 ldraw::SubfileReference::position() const
-{
-	return this->transformation[3];
-}
-
-void ldraw::SubfileReference::invert()
-{
-	this->isInverted = not this->isInverted;
-}
-
 Model* ldraw::SubfileReference::resolve(const ModelId callingModelId, DocumentManager* documents) const
 {
 	return documents->findDependencyByName(callingModelId, this->referenceName);
@@ -105,12 +91,12 @@
 
 QDataStream& ldraw::SubfileReference::serialize(QDataStream &stream) const
 {
-	return ColoredObject::serialize(stream) << this->transformation << this->referenceName << this->isInverted;
+	return CompoundObject::serialize(stream) << this->referenceName;
 }
 
 QDataStream& ldraw::SubfileReference::deserialize(QDataStream &stream)
 {
-	return ColoredObject::deserialize(stream) >> this->transformation >> this->referenceName >> this->isInverted;
+	return CompoundObject::deserialize(stream) >> this->referenceName;
 }
 
 QString ldraw::SubfileReference::toLDrawCode() const
--- a/src/linetypes/subfilereference.h	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/linetypes/subfilereference.h	Tue Mar 15 18:52:48 2022 +0200
@@ -1,5 +1,6 @@
 #pragma once
-#include "object.h"
+#include "compoundobject.h"
+#include "invert.h"
 
 class Model;
 
@@ -8,7 +9,7 @@
 	class SubfileReference;
 }
 
-class ldraw::SubfileReference : public ColoredObject
+class ldraw::SubfileReference : public CompoundObject
 {
 public:
 	SubfileReference() = default;
@@ -19,8 +20,6 @@
 	QVariant getProperty(Property property) const override;
 	QString textRepresentation() const override;
 	void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override;
-	glm::vec3 position() const;
-	void invert() override;
 	Model* resolve(const ModelId callingModelId, DocumentManager* documents) const;
 	Type typeIdentifier() const override;
 	QDataStream& serialize(QDataStream& stream) const override;
@@ -28,9 +27,7 @@
 	QString toLDrawCode() const override;
 	QString iconName() const override;
 	QString typeName() const override;
-	glm::mat4 transformation;
 	QString referenceName;
-	bool isInverted = false;
 protected:
 	void setProperty(SetPropertyResult* result, const PropertyKeyValue& pair) override;
 };
--- a/src/linetypes/triangle.cpp	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/linetypes/triangle.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -21,7 +21,7 @@
 		this->id));
 }
 
-void ldraw::Triangle::invert()
+void ldraw::Triangle::invert(GetPolygonsContext *)
 {
 	//    0 1 2
 	// -> 1 0 2
--- a/src/linetypes/triangle.h	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/linetypes/triangle.h	Tue Mar 15 18:52:48 2022 +0200
@@ -12,7 +12,7 @@
 	using PolygonObject<3>::PolygonObject;
 	QString textRepresentation() const override;
 	void getPolygons(std::vector<gl::Polygon>& polygons, GetPolygonsContext* context) const override;
-	void invert() override;
+	void invert(GetPolygonsContext*) override;
 	Type typeIdentifier() const override;
 	QString toLDrawCode() const override;
 	QString iconName() const override;
--- a/src/mainwindow.cpp	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/mainwindow.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -79,6 +79,7 @@
 		this, &MainWindow::actionSaveAs);
 	connect(this->ui->actionClose, &QAction::triggered, this, &MainWindow::actionClose);
 	connect(this->ui->actionDelete, &QAction::triggered, this, &MainWindow::actionDelete);
+	connect(this->ui->actionInvert, &QAction::triggered, this, &MainWindow::actionInvert);
 	connect(this->ui->tabs, &QTabWidget::tabCloseRequested, this, &MainWindow::handleTabCloseButton);
 	for (auto data : ::renderStyleButtons)
 	{
@@ -379,6 +380,34 @@
 }
 
 /**
+ * @brief Handles the "Invert" action
+ */
+void MainWindow::actionInvert()
+{
+	Document* document = this->currentDocument();
+	if (document != nullptr)
+	{
+		// TODO: simplify
+		std::unique_ptr<ModelEditor> modelEditor = document->editModel();
+		const std::optional<ModelId> modelId = this->documents.findIdForModel(&modelEditor->model());
+		if (modelId.has_value())
+		{
+			ldraw::GetPolygonsContext context = {
+				.modelId = modelId.value(),
+				.documents = &this->documents,
+			};
+			for (const ldraw::id_t id : document->selectedObjects())
+			{
+				modelEditor->modifyObject(id, [&context](ldraw::Object* object)
+				{
+					object->invert(&context);
+				});
+			}
+		}
+	}
+}
+
+/**
  * @brief Removes the document at the specified tab index
  * @param index
  */
--- a/src/mainwindow.h	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/mainwindow.h	Tue Mar 15 18:52:48 2022 +0200
@@ -49,6 +49,7 @@
 	void actionSaveAs();
 	void actionClose();
 	void actionDelete();
+	void actionInvert();
 	void handleTabCloseButton(int tabIndex);
 protected:
 	void changeEvent(QEvent* event) override;
--- a/src/mainwindow.ui	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/mainwindow.ui	Tue Mar 15 18:52:48 2022 +0200
@@ -30,7 +30,7 @@
      <x>0</x>
      <y>0</y>
      <width>800</width>
-     <height>31</height>
+     <height>27</height>
     </rect>
    </property>
    <widget class="QMenu" name="menuFile">
@@ -69,6 +69,7 @@
     <property name="title">
      <string>Edit</string>
     </property>
+    <addaction name="actionInvert"/>
     <addaction name="actionDelete"/>
     <addaction name="separator"/>
     <addaction name="actionGridFine"/>
@@ -120,6 +121,7 @@
    <attribute name="toolBarBreak">
     <bool>false</bool>
    </attribute>
+   <addaction name="actionInvert"/>
    <addaction name="actionDelete"/>
    <addaction name="actionGridFine"/>
    <addaction name="actionGridMedium"/>
@@ -312,6 +314,15 @@
     <string>Ctrl+3</string>
    </property>
   </action>
+  <action name="actionInvert">
+   <property name="icon">
+    <iconset resource="../ldforge.qrc">
+     <normaloff>:/icons/invert.png</normaloff>:/icons/invert.png</iconset>
+   </property>
+   <property name="text">
+    <string>Invert</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="../ldforge.qrc"/>
--- a/src/parser.cpp	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/parser.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -67,7 +67,7 @@
 		model.append(parseFromString(line));
 		if (invertNext)
 		{
-			model[model.size() - 1]->invert();
+			model[model.size() - 1]->invert(nullptr);
 		}
 		invertNext = false;
 	}
--- a/src/polygoncache.cpp	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/polygoncache.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -16,7 +16,7 @@
  * @param documents Documents to use to resolve subfile references
  * @return vector of GL polygons
  */
-std::vector<gl::Polygon> PolygonCache::getPolygons(DocumentManager* documents)
+const std::vector<gl::Polygon> &PolygonCache::getPolygons(DocumentManager* documents)
 {
 	if (this->needRecache)
 	{
--- a/src/polygoncache.h	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/polygoncache.h	Tue Mar 15 18:52:48 2022 +0200
@@ -7,7 +7,7 @@
 	Q_OBJECT
 public:
 	PolygonCache(Model* model);
-	std::vector<gl::Polygon> getPolygons(class DocumentManager* documents);
+	const std::vector<gl::Polygon>& getPolygons(class DocumentManager* documents);
 private:
 	void getObjectPolygons(
 		const int index,
--- a/src/ui/objecteditor.cpp	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/ui/objecteditor.cpp	Tue Mar 15 18:52:48 2022 +0200
@@ -1,9 +1,6 @@
-#include <QVBoxLayout>
+#include <QCheckBox>
+#include <QLineEdit>
 #include <QFormLayout>
-#include <QPushButton>
-#include <QLabel>
-#include <QSpinBox>
-#include <QSplitter>
 #include "objecteditor.h"
 #include "document.h"
 #include "modeleditor.h"
@@ -59,6 +56,22 @@
 		{
 			vec3Editor->setValue(value.value<glm::vec3>());
 		}
+		else
+		{
+			QCheckBox* checkBox = qobject_cast<QCheckBox*>(widget);
+			if (checkBox != nullptr)
+			{
+				checkBox->setChecked(value.toBool());
+			}
+			else
+			{
+				QLineEdit* lineEdit = qobject_cast<QLineEdit*>(widget);
+				if (lineEdit != nullptr)
+				{
+					lineEdit->setText(value.toString());
+				}
+			}
+		}
 	}
 }
 
@@ -66,7 +79,7 @@
 {
 	this->objectId = id;
 	const ldraw::Object* object = this->document->getModel().get(id);
-	this->ui.properties->setVisible(object != nullptr);
+	this->ui.properties->setEnabled(object != nullptr);
 	if (object != nullptr)
 	{
 		this->ui.typeNameLabel->setText("<b>" + titleCase(object->typeName()) + "</b>");
@@ -77,8 +90,8 @@
 			const auto it = this->propertyWidgets.find(property);
 			if (it != this->propertyWidgets.end())
 			{
-				it->first->setVisible(not value.isNull());
-				it->second->setVisible(not value.isNull());
+				it->first->setEnabled(not value.isNull());
+				it->second->setEnabled(not value.isNull());
 				if (not value.isNull())
 				{
 					setValueToWidget(it->second, value);
@@ -103,6 +116,16 @@
 	this->handlePropertyChange(this->sender(), QVariant::fromValue(value));
 }
 
+void ObjectEditor::handleBoolChange(bool value)
+{
+	this->handlePropertyChange(this->sender(), QVariant::fromValue(value));
+}
+
+void ObjectEditor::handleStringChange(const QString &value)
+{
+	this->handlePropertyChange(this->sender(), QVariant::fromValue(value));
+}
+
 QWidget* ObjectEditor::makeEditorWidgetForProperty(ldraw::Property property)
 {
 	QWidget* const parent = qobject_cast<QWidget*>(this->parent());
@@ -118,6 +141,18 @@
 		connect(editor, &Vec3Editor::valueChanged, this, &ObjectEditor::handleVec3Change);
 		return editor;
 	}
+	else if (ldraw::traits(property).type == qMetaTypeId<bool>())
+	{
+		QCheckBox* editor = new QCheckBox{{}, parent};
+		connect(editor, &QCheckBox::clicked, this, &ObjectEditor::handleBoolChange);
+		return editor;
+	}
+	else if (ldraw::traits(property).type == qMetaTypeId<QString>())
+	{
+		QLineEdit* editor = new QLineEdit{{}, parent};
+		connect(editor, &QLineEdit::textChanged, this, &ObjectEditor::handleStringChange);
+		return editor;
+	}
 	else
 	{
 		return nullptr;
--- a/src/ui/objecteditor.h	Sun Mar 13 20:26:28 2022 +0200
+++ b/src/ui/objecteditor.h	Tue Mar 15 18:52:48 2022 +0200
@@ -15,6 +15,8 @@
 private:
 	Q_SLOT void handleColorChange(ldraw::Color value);
 	Q_SLOT void handleVec3Change(const glm::vec3& value);
+	Q_SLOT void handleBoolChange(bool value);
+	Q_SLOT void handleStringChange(const QString& value);
 	class Ui_ObjectEditor& ui;
 	Document* const document;
 	ldraw::id_t objectId = ldraw::NULL_ID;

mercurial