diff --git a/QtGameEngine.pro b/QtGameEngine.pro
index 8b3afae..e61750b 100644
--- a/QtGameEngine.pro
+++ b/QtGameEngine.pro
@@ -1,18 +1,10 @@
-QT += core
-QT -= gui
-
-CONFIG += c++11
+QT += core gui widgets 3dcore 3drender 3dinput 3dextras
TARGET = QtGameEngine
-CONFIG += console
-CONFIG -= app_bundle
-
TEMPLATE = app
-SOURCES += main.cpp
-
# The following define makes your compiler emit warnings if you use
-# any feature of Qt which as been marked deprecated (the exact warnings
+# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
@@ -21,3 +13,26 @@ DEFINES += QT_DEPRECATED_WARNINGS
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
+
+
+SOURCES += main.cpp \
+ mainwindow.cpp \
+ houseplant.cpp \
+ renderableentity.cpp \
+ treemodel.cpp
+
+HEADERS += mainwindow.h \
+ houseplant.h \
+ renderableentity.h \
+ treemodel.h \
+ widgets.h
+
+FORMS += mainwindow.ui
+
+RESOURCES += \
+ resources.qrc \
+ chest.qrc \
+ houseplants.qrc \
+ metalbarrel.qrc \
+ obj.qrc \
+ textures.qrc
diff --git a/assets/chest/diffuse.webp b/assets/chest/diffuse.webp
new file mode 100644
index 0000000..ce985c1
Binary files /dev/null and b/assets/chest/diffuse.webp differ
diff --git a/assets/houseplants/bamboo.webp b/assets/houseplants/bamboo.webp
new file mode 100644
index 0000000..75eb539
Binary files /dev/null and b/assets/houseplants/bamboo.webp differ
diff --git a/assets/houseplants/bamboo_normal.webp b/assets/houseplants/bamboo_normal.webp
new file mode 100644
index 0000000..2ca653c
Binary files /dev/null and b/assets/houseplants/bamboo_normal.webp differ
diff --git a/assets/houseplants/cover.webp b/assets/houseplants/cover.webp
new file mode 100644
index 0000000..ac70f46
Binary files /dev/null and b/assets/houseplants/cover.webp differ
diff --git a/assets/houseplants/cover_normal.webp b/assets/houseplants/cover_normal.webp
new file mode 100644
index 0000000..793f82b
Binary files /dev/null and b/assets/houseplants/cover_normal.webp differ
diff --git a/assets/houseplants/palm.webp b/assets/houseplants/palm.webp
new file mode 100644
index 0000000..cf984fa
Binary files /dev/null and b/assets/houseplants/palm.webp differ
diff --git a/assets/houseplants/palm_normal.webp b/assets/houseplants/palm_normal.webp
new file mode 100644
index 0000000..87fbf7a
Binary files /dev/null and b/assets/houseplants/palm_normal.webp differ
diff --git a/assets/houseplants/pine.webp b/assets/houseplants/pine.webp
new file mode 100644
index 0000000..994afa1
Binary files /dev/null and b/assets/houseplants/pine.webp differ
diff --git a/assets/houseplants/pine_normal.webp b/assets/houseplants/pine_normal.webp
new file mode 100644
index 0000000..15e6849
Binary files /dev/null and b/assets/houseplants/pine_normal.webp differ
diff --git a/assets/houseplants/pot.webp b/assets/houseplants/pot.webp
new file mode 100644
index 0000000..45253c7
Binary files /dev/null and b/assets/houseplants/pot.webp differ
diff --git a/assets/houseplants/pot_normal.webp b/assets/houseplants/pot_normal.webp
new file mode 100644
index 0000000..bf09c94
Binary files /dev/null and b/assets/houseplants/pot_normal.webp differ
diff --git a/assets/houseplants/shrub.webp b/assets/houseplants/shrub.webp
new file mode 100644
index 0000000..fea7b58
Binary files /dev/null and b/assets/houseplants/shrub.webp differ
diff --git a/assets/houseplants/shrub_normal.webp b/assets/houseplants/shrub_normal.webp
new file mode 100644
index 0000000..8a67669
Binary files /dev/null and b/assets/houseplants/shrub_normal.webp differ
diff --git a/assets/houseplants/spikes.webp b/assets/houseplants/spikes.webp
new file mode 100644
index 0000000..cff2f08
Binary files /dev/null and b/assets/houseplants/spikes.webp differ
diff --git a/assets/houseplants/spikes_normal.webp b/assets/houseplants/spikes_normal.webp
new file mode 100644
index 0000000..e0557b9
Binary files /dev/null and b/assets/houseplants/spikes_normal.webp differ
diff --git a/assets/metalbarrel/diffus_black.webp b/assets/metalbarrel/diffus_black.webp
new file mode 100644
index 0000000..5e5e083
Binary files /dev/null and b/assets/metalbarrel/diffus_black.webp differ
diff --git a/assets/metalbarrel/diffus_blue.webp b/assets/metalbarrel/diffus_blue.webp
new file mode 100644
index 0000000..194d63b
Binary files /dev/null and b/assets/metalbarrel/diffus_blue.webp differ
diff --git a/assets/metalbarrel/diffus_green.webp b/assets/metalbarrel/diffus_green.webp
new file mode 100644
index 0000000..32bb9c1
Binary files /dev/null and b/assets/metalbarrel/diffus_green.webp differ
diff --git a/assets/metalbarrel/diffus_red.webp b/assets/metalbarrel/diffus_red.webp
new file mode 100644
index 0000000..b01cf79
Binary files /dev/null and b/assets/metalbarrel/diffus_red.webp differ
diff --git a/assets/metalbarrel/diffus_rust.webp b/assets/metalbarrel/diffus_rust.webp
new file mode 100644
index 0000000..302242b
Binary files /dev/null and b/assets/metalbarrel/diffus_rust.webp differ
diff --git a/assets/metalbarrel/diffus_stainless_steel.webp b/assets/metalbarrel/diffus_stainless_steel.webp
new file mode 100644
index 0000000..20ee66d
Binary files /dev/null and b/assets/metalbarrel/diffus_stainless_steel.webp differ
diff --git a/assets/metalbarrel/diffus_yellow.webp b/assets/metalbarrel/diffus_yellow.webp
new file mode 100644
index 0000000..b53a924
Binary files /dev/null and b/assets/metalbarrel/diffus_yellow.webp differ
diff --git a/assets/metalbarrel/normal_hard_bumps.webp b/assets/metalbarrel/normal_hard_bumps.webp
new file mode 100644
index 0000000..ef7407f
Binary files /dev/null and b/assets/metalbarrel/normal_hard_bumps.webp differ
diff --git a/assets/metalbarrel/normal_middle_bumps.webp b/assets/metalbarrel/normal_middle_bumps.webp
new file mode 100644
index 0000000..cfb2c58
Binary files /dev/null and b/assets/metalbarrel/normal_middle_bumps.webp differ
diff --git a/assets/metalbarrel/normal_no_bumps.webp b/assets/metalbarrel/normal_no_bumps.webp
new file mode 100644
index 0000000..cc92745
Binary files /dev/null and b/assets/metalbarrel/normal_no_bumps.webp differ
diff --git a/assets/metalbarrel/normal_soft_bumps.webp b/assets/metalbarrel/normal_soft_bumps.webp
new file mode 100644
index 0000000..757dc1d
Binary files /dev/null and b/assets/metalbarrel/normal_soft_bumps.webp differ
diff --git a/assets/metalbarrel/specular.webp b/assets/metalbarrel/specular.webp
new file mode 100644
index 0000000..50fbd92
Binary files /dev/null and b/assets/metalbarrel/specular.webp differ
diff --git a/assets/metalbarrel/specular_rust.webp b/assets/metalbarrel/specular_rust.webp
new file mode 100644
index 0000000..8527b3e
Binary files /dev/null and b/assets/metalbarrel/specular_rust.webp differ
diff --git a/assets/metalbarrel/specular_stainless_steel.webp b/assets/metalbarrel/specular_stainless_steel.webp
new file mode 100644
index 0000000..c05a797
Binary files /dev/null and b/assets/metalbarrel/specular_stainless_steel.webp differ
diff --git a/assets/textures/pattern_09/diffuse.webp b/assets/textures/pattern_09/diffuse.webp
new file mode 100644
index 0000000..b41ddb5
Binary files /dev/null and b/assets/textures/pattern_09/diffuse.webp differ
diff --git a/assets/textures/pattern_09/normal.webp b/assets/textures/pattern_09/normal.webp
new file mode 100644
index 0000000..a2b4a7e
Binary files /dev/null and b/assets/textures/pattern_09/normal.webp differ
diff --git a/assets/textures/pattern_09/readme.txt b/assets/textures/pattern_09/readme.txt
new file mode 100644
index 0000000..763ed34
--- /dev/null
+++ b/assets/textures/pattern_09/readme.txt
@@ -0,0 +1,5 @@
+These textures along with many others are available from:
+
+http://nobiax.deviantart.com/
+
+Many thanks to Nobiax for making these freely available!
diff --git a/assets/textures/pattern_09/specular.webp b/assets/textures/pattern_09/specular.webp
new file mode 100644
index 0000000..cbb764e
Binary files /dev/null and b/assets/textures/pattern_09/specular.webp differ
diff --git a/chest.qrc b/chest.qrc
new file mode 100644
index 0000000..86fac22
--- /dev/null
+++ b/chest.qrc
@@ -0,0 +1,6 @@
+
+
+ assets/chest/Chest.obj
+ assets/chest/diffuse.webp
+
+
diff --git a/houseplant.cpp b/houseplant.cpp
new file mode 100644
index 0000000..0dcf024
--- /dev/null
+++ b/houseplant.cpp
@@ -0,0 +1,144 @@
+#include "houseplant.h"
+
+#include
+
+const char *potNames[] = {
+ "cross",
+ "square",
+ "triangle",
+ "sphere"
+};
+
+const char *plantNames[] = {
+ "bamboo",
+ "palm",
+ "pine",
+ "spikes",
+ "shrub"
+};
+
+
+HousePlant::HousePlant(Qt3DCore::QNode *parent)
+ : Qt3DCore::QEntity(parent)
+ , m_pot(new RenderableEntity(this))
+ , m_plant(new RenderableEntity(m_pot))
+ , m_cover(new RenderableEntity(m_pot))
+ , m_potMaterial(new Qt3DExtras::QNormalDiffuseMapMaterial())
+ , m_plantMaterial(new Qt3DExtras::QNormalDiffuseMapAlphaMaterial())
+ , m_coverMaterial(new Qt3DExtras::QNormalDiffuseMapMaterial())
+ , m_potImage(new Qt3DRender::QTextureImage())
+ , m_potNormalImage(new Qt3DRender::QTextureImage())
+ , m_plantImage(new Qt3DRender::QTextureImage())
+ , m_plantNormalImage(new Qt3DRender::QTextureImage())
+ , m_coverImage(new Qt3DRender::QTextureImage())
+ , m_coverNormalImage(new Qt3DRender::QTextureImage())
+ , m_plantType(Bamboo)
+ , m_potShape(Cross)
+{
+ m_potMaterial->setObjectName("potMaterial");
+ m_plantMaterial->setObjectName("plantMaterial");
+ m_coverMaterial->setObjectName("coverMaterial");
+ m_potImage->setObjectName("potImage");
+ m_potNormalImage->setObjectName("potNormalImage");
+ m_plantImage->setObjectName("plantImage");
+ m_plantNormalImage->setObjectName("plantNormalImage");
+ m_coverImage->setObjectName("coverImage");
+ m_coverNormalImage->setObjectName("coverNormalImage");
+
+ m_pot->setObjectName("pot");
+ m_pot->transform()->setScale(0.03f);
+ m_pot->addComponent(m_potMaterial);
+
+ m_plant->setObjectName("plant");
+ m_plant->addComponent(m_plantMaterial);
+
+ m_cover->setObjectName("cover");
+ m_cover->addComponent(m_coverMaterial);
+
+ m_potMaterial->diffuse()->addTextureImage(m_potImage);
+ m_potMaterial->normal()->addTextureImage(m_potNormalImage);
+ m_plantMaterial->diffuse()->addTextureImage(m_plantImage);
+ m_plantMaterial->normal()->addTextureImage(m_plantNormalImage);
+ m_coverMaterial->diffuse()->addTextureImage(m_coverImage);
+ m_coverMaterial->normal()->addTextureImage(m_coverNormalImage);
+
+ updatePlantType();
+ updatePotShape();
+
+ m_coverImage->setSource(QUrl(QStringLiteral("qrc:/assets/houseplants/cover.webp")));
+ m_coverNormalImage->setSource(QUrl(QStringLiteral("qrc:/assets/houseplants/cover_normal.webp")));
+ m_potImage->setSource(QUrl(QStringLiteral("qrc:/assets/houseplants/pot.webp")));
+ m_potNormalImage->setSource(QUrl(QStringLiteral("qrc:/assets/houseplants/pot_normal.webp")));
+
+ m_potMaterial->setShininess(10.0f);
+ m_potMaterial->setSpecular(QColor::fromRgbF(0.75f, 0.75f, 0.75f, 1.0f));
+
+ m_plantMaterial->setShininess(10.0f);
+
+ m_coverMaterial->setSpecular(QColor::fromRgbF(0.05f, 0.05f, 0.05f, 1.0f));
+ m_coverMaterial->setShininess(5.0f);
+}
+
+HousePlant::~HousePlant()
+{
+}
+
+void HousePlant::setPotShape(HousePlant::PotShape shape)
+{
+ if (shape != m_potShape) {
+ m_potShape = shape;
+ updatePotShape();
+ }
+}
+
+void HousePlant::setPlantType(HousePlant::Plant plant)
+{
+ if (plant != m_plantType) {
+ m_plantType = plant;
+ updatePlantType();
+ }
+}
+
+HousePlant::PotShape HousePlant::potShape() const
+{
+ return m_potShape;
+}
+
+HousePlant::Plant HousePlant::plantType() const
+{
+ return m_plantType;
+}
+
+void HousePlant::setPosition(const QVector3D &pos)
+{
+ m_pot->transform()->setTranslation(pos);
+}
+
+void HousePlant::setScale(float scale)
+{
+ m_pot->transform()->setScale(scale);
+}
+
+QVector3D HousePlant::position() const
+{
+ return m_pot->transform()->translation();
+}
+
+float HousePlant::scale() const
+{
+ return m_pot->transform()->scale();
+}
+
+void HousePlant::updatePotShape()
+{
+ m_pot->mesh()->setSource(QUrl(QStringLiteral("qrc:/assets/houseplants/") + potNames[m_potShape] + QStringLiteral("-pot.obj")));
+ m_plant->mesh()->setSource(QUrl(QStringLiteral("qrc:/assets/houseplants/") + potNames[m_potShape] + QStringLiteral("-") + plantNames[m_plantType] + QStringLiteral(".obj")));
+}
+
+void HousePlant::updatePlantType()
+{
+ m_plant->mesh()->setSource(QUrl(QStringLiteral("qrc:/assets/houseplants/") + potNames[m_potShape] + QStringLiteral("-") + plantNames[m_plantType] + QStringLiteral(".obj")));
+
+ m_plantImage->setSource(QUrl(QStringLiteral("qrc:/assets/houseplants/") + plantNames[m_plantType] + QStringLiteral(".webp")));
+ m_plantNormalImage->setSource(QUrl(QStringLiteral("qrc:/assets/houseplants/") + plantNames[m_plantType] + QStringLiteral("_normal.webp")));
+}
diff --git a/houseplant.h b/houseplant.h
new file mode 100644
index 0000000..bc11cbd
--- /dev/null
+++ b/houseplant.h
@@ -0,0 +1,67 @@
+#ifndef HOUSEPLANT_H
+#define HOUSEPLANT_H
+
+#include "renderableentity.h"
+#include
+#include
+#include
+#include
+
+class HousePlant : public Qt3DCore::QEntity
+{
+ Q_OBJECT
+public:
+ explicit HousePlant(Qt3DCore::QNode *parent = 0);
+ ~HousePlant();
+
+ enum PotShape {
+ Cross = 0,
+ Square,
+ Triangle,
+ Sphere
+ };
+
+ enum Plant {
+ Bamboo = 0,
+ Palm,
+ Pine,
+ Spikes,
+ Shrub
+ };
+
+ void setPotShape(PotShape shape);
+ void setPlantType(Plant plant);
+
+ PotShape potShape() const;
+ Plant plantType() const;
+
+ void setPosition(const QVector3D &pos);
+ void setScale(float scale);
+
+ QVector3D position() const;
+ float scale() const;
+
+private:
+ RenderableEntity *m_pot;
+ RenderableEntity *m_plant;
+ RenderableEntity *m_cover;
+
+ Qt3DExtras::QNormalDiffuseMapMaterial *m_potMaterial;
+ Qt3DExtras::QNormalDiffuseMapAlphaMaterial *m_plantMaterial;
+ Qt3DExtras::QNormalDiffuseMapMaterial *m_coverMaterial;
+
+ Qt3DRender::QTextureImage *m_potImage;
+ Qt3DRender::QTextureImage *m_potNormalImage;
+ Qt3DRender::QTextureImage *m_plantImage;
+ Qt3DRender::QTextureImage *m_plantNormalImage;
+ Qt3DRender::QTextureImage *m_coverImage;
+ Qt3DRender::QTextureImage *m_coverNormalImage;
+
+ Plant m_plantType;
+ PotShape m_potShape;
+
+ void updatePotShape();
+ void updatePlantType();
+};
+
+#endif // HOUSEPLANT_H
diff --git a/houseplants.qrc b/houseplants.qrc
new file mode 100644
index 0000000..faa47dc
--- /dev/null
+++ b/houseplants.qrc
@@ -0,0 +1,53 @@
+
+
+ assets/houseplants/bamboo_normal.webp
+ assets/houseplants/bamboo.webp
+ assets/houseplants/cover_normal.webp
+ assets/houseplants/cover.webp
+ assets/houseplants/cross-bamboo.obj
+ assets/houseplants/cross-palm.obj
+ assets/houseplants/cross-pine.obj
+ assets/houseplants/cross-pot-cover.obj
+ assets/houseplants/cross-pot.obj
+ assets/houseplants/cross-shrub.obj
+ assets/houseplants/cross-spikes.obj
+ assets/houseplants/cylinder-bamboo.obj
+ assets/houseplants/cylinder-palm.obj
+ assets/houseplants/cylinder-pine.obj
+ assets/houseplants/cylinder-pot-cover.obj
+ assets/houseplants/cylinder-pot.obj
+ assets/houseplants/cylinder-shrub.obj
+ assets/houseplants/cylinder-spikes.obj
+ assets/houseplants/palm_normal.webp
+ assets/houseplants/palm.webp
+ assets/houseplants/pine_normal.webp
+ assets/houseplants/pine.webp
+ assets/houseplants/pot_normal.webp
+ assets/houseplants/pot.webp
+ assets/houseplants/shrub_normal.webp
+ assets/houseplants/shrub.webp
+ assets/houseplants/sphere-bamboo.obj
+ assets/houseplants/sphere-palm.obj
+ assets/houseplants/sphere-pine.obj
+ assets/houseplants/sphere-pot-cover.obj
+ assets/houseplants/sphere-pot.obj
+ assets/houseplants/sphere-shrub.obj
+ assets/houseplants/sphere-spikes.obj
+ assets/houseplants/spikes_normal.webp
+ assets/houseplants/spikes.webp
+ assets/houseplants/square-bamboo.obj
+ assets/houseplants/square-palm.obj
+ assets/houseplants/square-pine.obj
+ assets/houseplants/square-pot-cover.obj
+ assets/houseplants/square-pot.obj
+ assets/houseplants/square-shrub.obj
+ assets/houseplants/square-spikes.obj
+ assets/houseplants/triangle-bamboo.obj
+ assets/houseplants/triangle-palm.obj
+ assets/houseplants/triangle-pine.obj
+ assets/houseplants/triangle-pot-cover.obj
+ assets/houseplants/triangle-pot.obj
+ assets/houseplants/triangle-shrub.obj
+ assets/houseplants/triangle-spikes.obj
+
+
diff --git a/images/actionCopy.png b/images/actionCopy.png
new file mode 100644
index 0000000..d4efa8c
Binary files /dev/null and b/images/actionCopy.png differ
diff --git a/images/actionCut.png b/images/actionCut.png
new file mode 100644
index 0000000..a40707c
Binary files /dev/null and b/images/actionCut.png differ
diff --git a/images/actionNew.png b/images/actionNew.png
new file mode 100644
index 0000000..f8f179b
Binary files /dev/null and b/images/actionNew.png differ
diff --git a/images/actionOpen.png b/images/actionOpen.png
new file mode 100644
index 0000000..42a014f
Binary files /dev/null and b/images/actionOpen.png differ
diff --git a/images/actionPaste.png b/images/actionPaste.png
new file mode 100644
index 0000000..7a15be5
Binary files /dev/null and b/images/actionPaste.png differ
diff --git a/images/actionPause.png b/images/actionPause.png
new file mode 100644
index 0000000..62b9541
Binary files /dev/null and b/images/actionPause.png differ
diff --git a/images/actionQuit.png b/images/actionQuit.png
new file mode 100644
index 0000000..7729ac3
Binary files /dev/null and b/images/actionQuit.png differ
diff --git a/images/actionRedo.png b/images/actionRedo.png
new file mode 100644
index 0000000..baf28b4
Binary files /dev/null and b/images/actionRedo.png differ
diff --git a/images/actionRun.png b/images/actionRun.png
new file mode 100644
index 0000000..e652bd3
Binary files /dev/null and b/images/actionRun.png differ
diff --git a/images/actionSave.png b/images/actionSave.png
new file mode 100644
index 0000000..4206259
Binary files /dev/null and b/images/actionSave.png differ
diff --git a/images/actionSaveAs.png b/images/actionSaveAs.png
new file mode 100644
index 0000000..58f5f9a
Binary files /dev/null and b/images/actionSaveAs.png differ
diff --git a/images/actionStop.png b/images/actionStop.png
new file mode 100644
index 0000000..d24cb08
Binary files /dev/null and b/images/actionStop.png differ
diff --git a/images/actionUndo.png b/images/actionUndo.png
new file mode 100644
index 0000000..4b40512
Binary files /dev/null and b/images/actionUndo.png differ
diff --git a/main.cpp b/main.cpp
index 470a030..3a5a4a4 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,8 +1,91 @@
-#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "widgets.h"
+#include "mainwindow.h"
int main(int argc, char *argv[])
{
- QCoreApplication a(argc, argv);
+ QApplication a(argc, argv);
+
+ {
+ auto factory = new QItemEditorFactory;
+
+ factory->registerEditor(QVariant::Bool, new QStandardItemEditorCreator());
+ factory->registerEditor(QVariant::Int, new QStandardItemEditorCreator::min(), std::numeric_limits::max()> >());
+ factory->registerEditor(QVariant::UInt, new QStandardItemEditorCreator::min(), std::numeric_limits::max()> >());
+ factory->registerEditor(QVariant::LongLong, new QStandardItemEditorCreator::min(), std::numeric_limits::max()> >());
+ factory->registerEditor(QVariant::ULongLong, new QStandardItemEditorCreator::min(), std::numeric_limits::max()> >());
+ factory->registerEditor(QVariant::Double, new QStandardItemEditorCreator());
+ factory->registerEditor(QMetaType::Float, new QStandardItemEditorCreator());
+ factory->registerEditor(QVariant::ULongLong, new QStandardItemEditorCreator::min(), std::numeric_limits::max()> >());
+ //factory->registerEditor(QVariant::Map, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::List, Q_NULLPTR); //TODO
+ factory->registerEditor(QVariant::String, new QStandardItemEditorCreator());
+ //factory->registerEditor(QVariant::StringList, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::ByteArray, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::BitArray, Q_NULLPTR); //TODO
+ factory->registerEditor(QVariant::Date, new QStandardItemEditorCreator());
+ factory->registerEditor(QVariant::Time, new QStandardItemEditorCreator());
+ factory->registerEditor(QVariant::DateTime, new QStandardItemEditorCreator());
+ factory->registerEditor(QVariant::Url, new UrlCreator); //TODO
+ //factory->registerEditor(QVariant::Locale, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Rect, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::RectF, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Size, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::SizeF, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Line, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::LineF, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Point, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::PointF, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::RegExp, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::RegularExpression, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Hash, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::EasingCurve, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Uuid, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::ModelIndex, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::PersistentModelIndex, Q_NULLPTR); //TODO
+
+ //factory->registerEditor(QVariant::Font, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Pixmap, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Brush, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Color, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Palette, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Image, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Polygon, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Region, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Bitmap, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Cursor, Q_NULLPTR); //TODO
+ factory->registerEditor(QVariant::KeySequence, new QStandardItemEditorCreator()); //TODO
+ //factory->registerEditor(QVariant::Pen, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::TextLength, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::TextFormat, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Matrix, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Transform, Q_NULLPTR); //TODO
+ factory->registerEditor(QVariant::Matrix4x4, new Matrix4x4Creator);
+ factory->registerEditor(QVariant::Vector2D, new Vector2DCreator);
+ factory->registerEditor(QVariant::Vector3D, new Vector3DCreator);
+ factory->registerEditor(QVariant::Vector4D, new Vector4DCreator);
+ factory->registerEditor(QVariant::Quaternion, new QuaternionCreator);
+ //factory->registerEditor(QVariant::PolygonF, Q_NULLPTR); //TODO
+ //factory->registerEditor(QVariant::Icon, Q_NULLPTR); //TODO
+
+ //factory->registerEditor(QVariant::SizePolicy, Q_NULLPTR); //TODO
+
+ QItemEditorFactory::setDefaultFactory(factory);
+ }
+
+ MainWindow w;
+ w.show();
return a.exec();
}
diff --git a/mainwindow.cpp b/mainwindow.cpp
new file mode 100644
index 0000000..1734bfe
--- /dev/null
+++ b/mainwindow.cpp
@@ -0,0 +1,478 @@
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "houseplant.h"
+#include "treemodel.h"
+
+MainWindow::MainWindow(QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow),
+ m_view()
+{
+ ui->setupUi(this);
+
+ ui->actionNew->setShortcut(QKeySequence::New);
+ ui->actionOpen->setShortcut(QKeySequence::Open);
+ ui->actionSave->setShortcut(QKeySequence::Save);
+ ui->actionSaveAs->setShortcut(QKeySequence::SaveAs);
+ ui->actionQuit->setShortcut(QKeySequence::Quit);
+
+ ui->actionUndo->setShortcut(QKeySequence::Undo);
+ ui->actionRedo->setShortcut(QKeySequence::Redo);
+ ui->actionCut->setShortcut(QKeySequence::Cut);
+ ui->actionCopy->setShortcut(QKeySequence::Copy);
+ ui->actionPaste->setShortcut(QKeySequence::Paste);
+
+ connect(ui->actionStart, &QAction::triggered, this, &MainWindow::start);
+ connect(ui->actionPause, &QAction::triggered, this, &MainWindow::pause);
+ connect(ui->actionStop, &QAction::triggered, this, &MainWindow::stop);
+
+ ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(ui->treeView, &QWidget::customContextMenuRequested, this, &MainWindow::customContextMenuRequested);
+
+ connect(ui->lineEdit, &QLineEdit::returnPressed, this, &MainWindow::returnPressed);
+
+ m_view.defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f)));
+
+ ui->centralWidget->layout()->addWidget(QWidget::createWindowContainer(&m_view, ui->centralWidget));
+
+ auto sceneRoot = new Qt3DCore::QEntity();
+ sceneRoot->setObjectName("sceneRoot");
+
+ {
+ auto basicCamera = m_view.camera();
+ basicCamera->setObjectName("basicCamera");
+ basicCamera->setProjectionType(Qt3DRender::QCameraLens::PerspectiveProjection);
+ basicCamera->setUpVector(QVector3D(0.0f, 1.0f, 0.0f));
+ basicCamera->setViewCenter(QVector3D(0.0f, 3.5f, 0.0f));
+ basicCamera->setPosition(QVector3D(0.0f, 3.5f, 25.0f));
+
+ {
+ auto camController = new Qt3DExtras::QFirstPersonCameraController(sceneRoot);
+ camController->setObjectName("camController");
+ camController->setCamera(basicCamera);
+ }
+ }
+
+ {
+ auto planeEntity = new Qt3DCore::QEntity(sceneRoot);
+ planeEntity->setObjectName("planeEntity");
+
+ {
+ auto mesh = new Qt3DExtras::QPlaneMesh;
+ mesh->setObjectName("mesh");
+ mesh->setHeight(100.0f);
+ mesh->setWidth(100.0f);
+ mesh->setMeshResolution(QSize(20, 20));
+ planeEntity->addComponent(mesh);
+ }
+
+ {
+ auto transform = new Qt3DCore::QTransform();
+ transform->setObjectName("transform");
+ planeEntity->addComponent(transform);
+ }
+
+ {
+ auto normalDiffuseSpecularMapMaterial = new Qt3DExtras::QNormalDiffuseSpecularMapMaterial();
+ normalDiffuseSpecularMapMaterial->setObjectName("normalDiffuseSpecularMapMaterial");
+ normalDiffuseSpecularMapMaterial->setTextureScale(10.0f);
+ normalDiffuseSpecularMapMaterial->setShininess(80.0f);
+ normalDiffuseSpecularMapMaterial->setAmbient(QColor::fromRgbF(0.2f, 0.2f, 0.2f, 1.0f));
+
+ {
+ auto diffuseImage = new Qt3DRender::QTextureImage();
+ diffuseImage->setObjectName("diffuseImage");
+ diffuseImage->setSource(QUrl(QStringLiteral("qrc:/assets/textures/pattern_09/diffuse.webp")));
+ normalDiffuseSpecularMapMaterial->diffuse()->addTextureImage(diffuseImage);
+ }
+
+ {
+ auto specularImage = new Qt3DRender::QTextureImage();
+ specularImage->setObjectName("specularImage");
+ specularImage->setSource(QUrl(QStringLiteral("qrc:/assets/textures/pattern_09/specular.webp")));
+ normalDiffuseSpecularMapMaterial->specular()->addTextureImage(specularImage);
+ }
+
+ {
+ auto normalImage = new Qt3DRender::QTextureImage();
+ normalImage->setObjectName("normalImage");
+ normalImage->setSource(QUrl((QStringLiteral("qrc:/assets/textures/pattern_09/normal.webp"))));
+ normalDiffuseSpecularMapMaterial->normal()->addTextureImage(normalImage);
+ }
+
+ planeEntity->addComponent(normalDiffuseSpecularMapMaterial);
+ }
+ }
+
+ {
+ auto chest = new Qt3DCore::QEntity(sceneRoot);
+ chest->setObjectName("chest");
+
+ {
+ auto mesh = new Qt3DRender::QMesh();
+ mesh->setObjectName("mesh");
+ mesh->setSource(QUrl(QStringLiteral("qrc:/assets/chest/Chest.obj")));
+ chest->addComponent(mesh);
+ }
+
+ {
+ auto transform = new Qt3DCore::QTransform();
+ transform->setObjectName("transform");
+ transform->setScale(0.03f);
+ chest->addComponent(transform);
+ }
+
+ {
+ auto diffuseMapMaterial = new Qt3DExtras::QDiffuseMapMaterial();
+ diffuseMapMaterial->setObjectName("diffuseMapMaterial");
+ diffuseMapMaterial->setSpecular(QColor::fromRgbF(0.2f, 0.2f, 0.2f, 1.0f));
+ diffuseMapMaterial->setShininess(2.0f);
+
+ {
+ auto chestDiffuseImage = new Qt3DRender::QTextureImage();
+ chestDiffuseImage->setObjectName("chestDiffuseImage");
+ chestDiffuseImage->setSource(QUrl(QStringLiteral("qrc:/assets/chest/diffuse.webp")));
+ diffuseMapMaterial->diffuse()->addTextureImage(chestDiffuseImage);
+ }
+
+ chest->addComponent(diffuseMapMaterial);
+ }
+ }
+
+ {
+ auto trefoil = new Qt3DCore::QEntity(sceneRoot);
+ trefoil->setObjectName("trefoil");
+
+ {
+ auto mesh = new Qt3DRender::QMesh();
+ mesh->setSource(QUrl("qrc:/assets/obj/trefoil.obj"));
+ trefoil->addComponent(mesh);
+ }
+
+ {
+ auto transform = new Qt3DCore::QTransform();
+ transform->setTranslation(QVector3D(0.0f, 3.5f, 0.0f));
+ transform->setScale(0.5f);
+
+ {
+ auto animation = new QPropertyAnimation(transform);
+ animation->setObjectName("animation");
+ animation->setDuration(2000);
+ animation->setStartValue(0.0f);
+ animation->setEndValue(360.0f);
+ animation->setLoopCount(-1);
+ animation->setTargetObject(transform);
+ animation->setPropertyName("rotationY");
+ m_animations << animation;
+ }
+
+ trefoil->addComponent(transform);
+ }
+
+ {
+ auto phongMaterial = new Qt3DExtras::QPhongMaterial();
+ phongMaterial->setObjectName("phongMaterial");
+ phongMaterial->setDiffuse(QColor(204, 205, 75)); // Safari Yellow #cccd4b
+ phongMaterial->setSpecular(Qt::white);
+ trefoil->addComponent(phongMaterial);
+ }
+ }
+
+ auto createBarrel = [=](const QString &name, const QVector3D &translation, float shininess, const QString &meshPath, const QString &diffuseTexturePath, const QString &normaleTexturePath, const QString &specularTexturePath){
+ auto barrel = new Qt3DCore::QEntity(sceneRoot);
+ barrel->setObjectName(name);
+
+ {
+ auto mesh = new Qt3DRender::QMesh();
+ mesh->setObjectName("mesh");
+ mesh->setSource(QUrl(meshPath));
+ barrel->addComponent(mesh);
+ }
+
+ {
+ auto transform = new Qt3DCore::QTransform();
+ transform->setObjectName("transform");
+ transform->setScale(0.03f);
+ transform->setTranslation(translation);
+ barrel->addComponent(transform);
+ }
+
+ {
+ auto material = new Qt3DExtras::QNormalDiffuseSpecularMapMaterial();
+ material->setObjectName("material");
+ material->setShininess(shininess);
+
+ material->diffuse()->setObjectName("diffuseTexture");
+
+ {
+ auto diffuseTextureImage = new Qt3DRender::QTextureImage();
+ diffuseTextureImage->setObjectName("diffuseTextureImage");
+ diffuseTextureImage->setSource(QUrl(diffuseTexturePath));
+
+ material->diffuse()->addTextureImage(diffuseTextureImage);
+ }
+
+ material->normal()->setObjectName("normalTexture");
+
+ {
+ auto normalTextureImage = new Qt3DRender::QTextureImage();
+ normalTextureImage->setObjectName("normalTextureImage");
+ normalTextureImage->setSource(QUrl(normaleTexturePath));
+
+ material->normal()->addTextureImage(normalTextureImage);
+ }
+
+ material->specular()->setObjectName("specularTexture");
+
+ {
+ auto specularTextureImage = new Qt3DRender::QTextureImage();
+ specularTextureImage->setObjectName("specularTextureImage");
+ specularTextureImage->setSource(QUrl(specularTexturePath));
+
+ material->specular()->addTextureImage(specularTextureImage);
+ }
+
+ barrel->addComponent(material);
+ }
+ };
+
+ createBarrel("basicBarrel", QVector3D(8.0f, 0.0f, 0.0f), 10.0f,
+ QStringLiteral("qrc:/assets/metalbarrel/metal_barrel.obj"),
+ QStringLiteral("qrc:/assets/metalbarrel/diffus_red.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/normal_no_bumps.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/specular.webp"));
+
+ createBarrel("rustyBarrel", QVector3D(10.0f, 0.0f, 0.0f), 10.0f,
+ QStringLiteral("qrc:/assets/metalbarrel/metal_barrel.obj"),
+ QStringLiteral("qrc:/assets/metalbarrel/diffus_rust.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/normal_hard_bumps.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/specular_rust.webp"));
+
+ createBarrel("blueBarrel", QVector3D(12.0f, 0.0f, 0.0f), 10.0f,
+ QStringLiteral("qrc:/assets/metalbarrel/metal_barrel.obj"),
+ QStringLiteral("qrc:/assets/metalbarrel/diffus_blue.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/normal_middle_bumps.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/specular_rust.webp"));
+
+ createBarrel("greenBarrel", QVector3D(14.0f, 0.0f, 0.0f), 10.0f,
+ QStringLiteral("qrc:/assets/metalbarrel/metal_barrel.obj"),
+ QStringLiteral("qrc:/assets/metalbarrel/diffus_green.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/normal_soft_bumps.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/specular_rust.webp"));
+
+ createBarrel("stainlessBarrel", QVector3D(16.0f, 0.0f, 0.0f), 150.0f,
+ QStringLiteral("qrc:/assets/metalbarrel/metal_barrel.obj"),
+ QStringLiteral("qrc:/assets/metalbarrel/diffus_stainless_steel.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/normal_no_bumps.webp"),
+ QStringLiteral("qrc:/assets/metalbarrel/specular_stainless_steel.webp"));
+
+ {
+ auto squareBamboo = new HousePlant(sceneRoot);
+ squareBamboo->setObjectName("squareBamboo");
+ squareBamboo->setPotShape(HousePlant::Square);
+ squareBamboo->setPosition(QVector3D(4.0f, 0.0f, 0.0f));
+ }
+
+ {
+ auto trianglePalm = new HousePlant(sceneRoot);
+ trianglePalm->setObjectName("trianglePalm");
+ trianglePalm->setPlantType(HousePlant::Palm);
+ trianglePalm->setPotShape(HousePlant::Triangle);
+ trianglePalm->setPosition(QVector3D(0.0f, 0.0f, 4.0f));
+ }
+
+ {
+ auto spherePine = new HousePlant(sceneRoot);
+ spherePine->setObjectName("spherePine");
+ spherePine->setPlantType(HousePlant::Pine);
+ spherePine->setPotShape(HousePlant::Sphere);
+ spherePine->setPosition(QVector3D(-4.0f, 0.0f, 0.0f));
+ }
+
+ {
+ auto crossSpikes = new HousePlant(sceneRoot);
+ crossSpikes->setObjectName("crossSpikes");
+ crossSpikes->setPlantType(HousePlant::Spikes);
+ crossSpikes->setPosition(QVector3D(0.0f, 0.0f, -4.0f));
+ }
+
+ {
+ auto crossPalm = new HousePlant(sceneRoot);
+ crossPalm->setObjectName("crossPalm");
+ crossPalm->setPlantType(HousePlant::Palm);
+ crossPalm->setPosition(QVector3D(0.0f, 0.0f, -8.0f));
+ crossPalm->setScale(0.05f);
+ }
+
+ {
+ auto crossShrub = new HousePlant(sceneRoot);
+ crossShrub->setObjectName("crossShrub");
+ crossShrub->setPlantType(HousePlant::Shrub);
+ crossShrub->setPosition(QVector3D(0.0f, 0.0f, 8.0f));
+ crossShrub->setScale(0.05f);
+ }
+
+ {
+ auto airplane = new Qt3DCore::QEntity(sceneRoot);
+ airplane->setObjectName("airplane");
+
+ {
+ auto mesh = new Qt3DRender::QMesh();
+ mesh->setObjectName("mesh");
+ mesh->setSource(QUrl(QStringLiteral("qrc:/assets/obj/toyplane.obj")));
+ airplane->addComponent(mesh);
+ }
+
+ {
+ auto transform = new Qt3DCore::QTransform();
+ transform->setObjectName("transform");
+ transform->setTranslation(QVector3D(0.0f, 5.0f, -20.0f));
+ transform->setScale(0.1f);
+ airplane->addComponent(transform);
+
+ {
+ auto animation = new QPropertyAnimation(transform);
+ animation->setObjectName("animation");
+ animation->setDuration(3000);
+ animation->setStartValue(0.0f);
+ animation->setEndValue(360.0f);
+ animation->setLoopCount(-1);
+ animation->setTargetObject(transform);
+ animation->setPropertyName("rotationX");
+ m_animations << animation;
+ }
+ }
+
+ {
+ auto phongMaterial = new Qt3DExtras::QPhongMaterial();
+ phongMaterial->setObjectName("phongMaterial");
+ phongMaterial->setDiffuse(QColor(150, 150, 150));
+ phongMaterial->setSpecular(Qt::white);
+ airplane->addComponent(phongMaterial);
+ }
+ }
+
+ m_view.setRootEntity(sceneRoot);
+
+ ui->treeView->setModel(new TreeModel(sceneRoot));
+ ui->treeView->expandAll();
+ connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &MainWindow::currentRowChanged);
+}
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
+
+void MainWindow::customContextMenuRequested(const QPoint &pos)
+{
+ auto index = ui->treeView->indexAt(pos);
+ if(!index.isValid())
+ return;
+
+ auto entity = static_cast(index.internalPointer());
+
+ QMenu menu;
+ auto switchEnabled = menu.addAction(entity->isEnabled() ? tr("Disable") : tr("Enable"));
+ auto selectedAction = menu.exec(ui->treeView->mapToGlobal(pos));
+
+ if(selectedAction == switchEnabled)
+ entity->setEnabled(!entity->isEnabled());
+}
+
+void MainWindow::currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
+{
+ qDebug() << "currentRowChanged";
+
+ if(!current.isValid())
+ return;
+
+ while(ui->formLayout->rowCount() > 0)
+ ui->formLayout->removeRow(0);
+
+ auto entity = static_cast(current.internalPointer());
+
+ for(int i = 0; i < entity->metaObject()->propertyCount(); i++)
+ {
+ auto property = entity->metaObject()->property(i);
+
+ auto type = property.type();
+
+ auto widget = QItemEditorFactory::defaultFactory()->createEditor(type, ui->scrollAreaWidgetContents);
+ if(widget)
+ widget->setProperty(QItemEditorFactory::defaultFactory()->valuePropertyName(type), entity->property(property.name()));
+ else
+ {
+ qWarning() << "no widget for" << property.name() << "(" << property.type() << ")";
+ widget = new QLabel(QString("%0").arg(tr("No widget for %0").arg(QString(QVariant::typeToName(type)).toHtmlEscaped())), ui->scrollAreaWidgetContents);
+ }
+
+ ui->formLayout->addRow(property.name(), widget);
+ }
+}
+
+void MainWindow::returnPressed()
+{
+ ui->textBrowser->append(QString("%0 [DEBUG]: Tried to execute \"%1\"").arg(QTime::currentTime().toString()).arg(ui->lineEdit->text()));
+ ui->textBrowser->verticalScrollBar()->setValue(ui->textBrowser->verticalScrollBar()->maximum());
+
+ ui->lineEdit->setText(QString());
+ ui->lineEdit->focusWidget();
+}
+
+void MainWindow::start()
+{
+ for(auto animation : m_animations)
+ animation->start();
+
+ ui->actionStart->setEnabled(false);
+ ui->actionPause->setEnabled(true);
+ ui->actionStop->setEnabled(true);
+}
+
+void MainWindow::pause()
+{
+ for(auto animation : m_animations)
+ animation->pause();
+
+ ui->actionStart->setEnabled(true);
+ ui->actionPause->setEnabled(false);
+}
+
+void MainWindow::stop()
+{
+ for(auto animation : m_animations)
+ {
+ animation->setCurrentTime(0);
+ animation->stop();
+ }
+
+ ui->actionStart->setEnabled(true);
+ ui->actionPause->setEnabled(false);
+ ui->actionStop->setEnabled(false);
+}
diff --git a/mainwindow.h b/mainwindow.h
new file mode 100644
index 0000000..470d9fa
--- /dev/null
+++ b/mainwindow.h
@@ -0,0 +1,36 @@
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include
+
+#include
+
+class QModelIndex;
+class QPropertyAnimation;
+
+namespace Ui { class MainWindow; }
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(QWidget *parent = 0);
+ ~MainWindow();
+
+private Q_SLOTS:
+ void customContextMenuRequested(const QPoint &pos);
+ void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
+ void returnPressed();
+ void start();
+ void pause();
+ void stop();
+
+private:
+ Ui::MainWindow *ui;
+
+ Qt3DExtras::Qt3DWindow m_view;
+ QList m_animations;
+};
+
+#endif // MAINWINDOW_H
diff --git a/mainwindow.ui b/mainwindow.ui
new file mode 100644
index 0000000..e7167b6
--- /dev/null
+++ b/mainwindow.ui
@@ -0,0 +1,330 @@
+
+
+ MainWindow
+
+
+
+ 0
+ 0
+ 1024
+ 768
+
+
+
+ MainWindow
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+
+
+
+
+ TopToolBarArea
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+ Console
+
+
+ 8
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+ Nodes
+
+
+ 2
+
+
+
+
+ 350
+ 0
+
+
+
+
+
+
+ Properties
+
+
+ 2
+
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 348
+ 92
+
+
+
+
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionNew.png:/EngineTest/images/actionNew.png
+
+
+ &New
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionOpen.png:/EngineTest/images/actionOpen.png
+
+
+ &Open
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionSave.png:/EngineTest/images/actionSave.png
+
+
+ &Save
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionSaveAs.png:/EngineTest/images/actionSaveAs.png
+
+
+ Save &As
+
+
+
+
+ true
+
+
+
+ :/EngineTest/images/actionQuit.png:/EngineTest/images/actionQuit.png
+
+
+ &Quit
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionUndo.png:/EngineTest/images/actionUndo.png
+
+
+ &Undo
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionRedo.png:/EngineTest/images/actionRedo.png
+
+
+ &Redo
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionCut.png:/EngineTest/images/actionCut.png
+
+
+ &Cut
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionCopy.png:/EngineTest/images/actionCopy.png
+
+
+ C&opy
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionPaste.png:/EngineTest/images/actionPaste.png
+
+
+ &Paste
+
+
+
+
+
+ :/EngineTest/images/actionRun.png:/EngineTest/images/actionRun.png
+
+
+ Sta&rt
+
+
+ Start
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionPause.png:/EngineTest/images/actionPause.png
+
+
+ &Pause
+
+
+
+
+ false
+
+
+
+ :/EngineTest/images/actionStop.png:/EngineTest/images/actionStop.png
+
+
+ &Stop
+
+
+
+
+
+
+
+
+
+ actionQuit
+ triggered()
+ MainWindow
+ close()
+
+
+ -1
+ -1
+
+
+ 511
+ 383
+
+
+
+
+
diff --git a/metalbarrel.qrc b/metalbarrel.qrc
new file mode 100644
index 0000000..43381ba
--- /dev/null
+++ b/metalbarrel.qrc
@@ -0,0 +1,19 @@
+
+
+ assets/metalbarrel/diffus_black.webp
+ assets/metalbarrel/diffus_blue.webp
+ assets/metalbarrel/diffus_green.webp
+ assets/metalbarrel/diffus_red.webp
+ assets/metalbarrel/diffus_rust.webp
+ assets/metalbarrel/diffus_stainless_steel.webp
+ assets/metalbarrel/diffus_yellow.webp
+ assets/metalbarrel/metal_barrel.obj
+ assets/metalbarrel/normal_hard_bumps.webp
+ assets/metalbarrel/normal_middle_bumps.webp
+ assets/metalbarrel/normal_no_bumps.webp
+ assets/metalbarrel/normal_soft_bumps.webp
+ assets/metalbarrel/specular_rust.webp
+ assets/metalbarrel/specular_stainless_steel.webp
+ assets/metalbarrel/specular.webp
+
+
diff --git a/obj.qrc b/obj.qrc
new file mode 100644
index 0000000..b8134bf
--- /dev/null
+++ b/obj.qrc
@@ -0,0 +1,10 @@
+
+
+ assets/textures/pattern_09/specular.webp
+ assets/textures/pattern_09/normal.webp
+ assets/textures/pattern_09/diffuse.webp
+ assets/obj/trefoil.obj
+ assets/obj/toyplane.obj
+ assets/obj/ball.obj
+
+
diff --git a/renderableentity.cpp b/renderableentity.cpp
new file mode 100644
index 0000000..8424791
--- /dev/null
+++ b/renderableentity.cpp
@@ -0,0 +1,24 @@
+#include "renderableentity.h"
+
+RenderableEntity::RenderableEntity(Qt3DCore::QNode *parent)
+ : Qt3DCore::QEntity(parent)
+ , m_mesh(new Qt3DRender::QMesh())
+ , m_transform(new Qt3DCore::QTransform())
+{
+ m_mesh->setObjectName("mesh");
+
+ m_transform->setObjectName("transform");
+
+ addComponent(m_mesh);
+ addComponent(m_transform);
+}
+
+Qt3DRender::QMesh *RenderableEntity::mesh() const
+{
+ return m_mesh;
+}
+
+Qt3DCore::QTransform *RenderableEntity::transform() const
+{
+ return m_transform;
+}
diff --git a/renderableentity.h b/renderableentity.h
new file mode 100644
index 0000000..13befb8
--- /dev/null
+++ b/renderableentity.h
@@ -0,0 +1,21 @@
+#ifndef RENDERABLEENTITY_H
+#define RENDERABLEENTITY_H
+
+#include
+#include
+#include
+
+class RenderableEntity : public Qt3DCore::QEntity
+{
+public:
+ RenderableEntity(Qt3DCore::QNode *parent = 0);
+
+ Qt3DRender::QMesh *mesh() const;
+ Qt3DCore::QTransform *transform() const;
+
+private:
+ Qt3DRender::QMesh *m_mesh;
+ Qt3DCore::QTransform *m_transform;
+};
+
+#endif // RENDERABLEENTITY_H
diff --git a/resources.qrc b/resources.qrc
new file mode 100644
index 0000000..1193f6c
--- /dev/null
+++ b/resources.qrc
@@ -0,0 +1,17 @@
+
+
+ images/actionCopy.png
+ images/actionCut.png
+ images/actionNew.png
+ images/actionOpen.png
+ images/actionPaste.png
+ images/actionPause.png
+ images/actionQuit.png
+ images/actionRedo.png
+ images/actionRun.png
+ images/actionSave.png
+ images/actionSaveAs.png
+ images/actionStop.png
+ images/actionUndo.png
+
+
diff --git a/textures.qrc b/textures.qrc
new file mode 100644
index 0000000..ef70706
--- /dev/null
+++ b/textures.qrc
@@ -0,0 +1,7 @@
+
+
+ assets/textures/pattern_09/specular.webp
+ assets/textures/pattern_09/normal.webp
+ assets/textures/pattern_09/diffuse.webp
+
+
diff --git a/treemodel.cpp b/treemodel.cpp
new file mode 100644
index 0000000..771b4ef
--- /dev/null
+++ b/treemodel.cpp
@@ -0,0 +1,169 @@
+#include "treemodel.h"
+
+#include
+#include
+
+TreeModel::TreeModel(Qt3DCore::QEntity *root, QObject *parent) :
+ QAbstractItemModel(parent),
+ m_root(root)
+{
+
+}
+
+QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (!hasIndex(row, column, parent))
+ return QModelIndex();
+
+ return createIndex(row, column, (parent.isValid() ? static_cast(parent.internalPointer()) : root())->childNodes().at(row));
+}
+
+QModelIndex TreeModel::parent(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QModelIndex();
+
+ auto parent = static_cast(index.internalPointer())->parentNode();
+
+ if (parent == root())
+ return QModelIndex();
+
+ int parentRow = 0;
+
+ if(parent->parentNode())
+ parentRow = parent->parentNode()->childNodes().indexOf(parent);
+
+ return createIndex(parentRow, 0, parent);
+}
+
+int TreeModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.column() > 0)
+ return 0;
+
+ return (parent.isValid() ? static_cast(parent.internalPointer()) : root())->childNodes().count();
+}
+
+int TreeModel::columnCount(const QModelIndex &parent) const
+{
+ if (parent.column() > 0)
+ return 0;
+
+ return 3; //(parent.isValid() ? static_cast(parent.internalPointer()) : root())->columnCount();
+}
+
+QVariant TreeModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ switch(index.column())
+ {
+ case 0:
+ {
+ auto name = static_cast(index.internalPointer())->objectName();
+ switch(role)
+ {
+ case Qt::DisplayRole:
+ if(name.isNull())
+ return tr("NULL");
+ else
+ return name;
+ case Qt::EditRole:
+ return name;
+ case Qt::FontRole:
+ if(name.isNull())
+ {
+ QFont font;
+ font.setItalic(true);
+ return font;
+ }
+ default:
+ return QVariant();
+ }
+ }
+ case 1:
+ {
+ switch(role)
+ {
+ case Qt::DisplayRole:
+ case Qt::EditRole:
+ return static_cast(index.internalPointer())->metaObject()->className();
+ default:
+ return QVariant();
+ }
+ }
+ case 2:
+ {
+ auto enabled = static_cast(index.internalPointer())->isEnabled();
+ switch(role)
+ {
+ case Qt::DisplayRole:
+ return enabled ? tr("true") : tr("false");
+ case Qt::EditRole:
+ return enabled;
+ default:
+ return QVariant();
+ }
+ }
+ }
+
+ return QVariant();
+}
+
+QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ switch(orientation)
+ {
+ case Qt::Horizontal:
+ switch(section) {
+ case 0:
+ {
+ switch(role)
+ {
+ case Qt::DisplayRole:
+ case Qt::EditRole:
+ return tr("Name");
+ default: return QVariant();
+ }
+ }
+ case 1:
+ {
+ switch(role)
+ {
+ case Qt::DisplayRole:
+ case Qt::EditRole:
+ return tr("Typ");
+ default: return QVariant();
+ }
+ }
+ case 2:
+ {
+ switch(role)
+ {
+ case Qt::DisplayRole:
+ case Qt::EditRole:
+ return tr("Enabled");
+ default: return QVariant();
+ }
+ }
+ default: return QVariant();
+ }
+ default: return QVariant();
+ }
+
+ return QVariant();
+}
+
+//Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
+//{
+// if (!index.isValid())
+// return Qt::ItemFlags();
+
+// return static_cast(index.internalPointer())->flags();
+//}
+
+Qt3DCore::QEntity *TreeModel::root() const
+{
+ return m_root;
+}
diff --git a/treemodel.h b/treemodel.h
new file mode 100644
index 0000000..5d2a6ba
--- /dev/null
+++ b/treemodel.h
@@ -0,0 +1,34 @@
+#ifndef TREEMODEL_H
+#define TREEMODEL_H
+
+#include
+#include
+
+namespace Qt3DCore { class QEntity; }
+
+class TreeModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ explicit TreeModel(Qt3DCore::QEntity *root, QObject *parent = 0);
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+ QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+
+ QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
+
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+
+ //Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;
+
+ Qt3DCore::QEntity *root() const;
+
+private:
+ Qt3DCore::QEntity *m_root;
+};
+
+#endif // TREEMODEL_H
diff --git a/widgets.h b/widgets.h
new file mode 100644
index 0000000..2aeee87
--- /dev/null
+++ b/widgets.h
@@ -0,0 +1,388 @@
+#ifndef WIDGETS_H
+#define WIDGETS_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+class UrlWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QUrl value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ inline UrlWidget(QWidget *parent = Q_NULLPTR) : QWidget(parent)
+ {
+ auto layout = new QHBoxLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_lineEdit = new QLineEdit(this));
+ {
+ auto toolButton = new QToolButton(this);
+ connect(toolButton, &QAbstractButton::pressed, this, &UrlWidget::pressed);
+ layout->addWidget(toolButton);
+ }
+ setLayout(layout);
+ }
+
+ inline QUrl value() const
+ {
+ return QUrl(m_lineEdit->text());
+ }
+
+ inline void setValue(const QUrl &value)
+ {
+ m_lineEdit->setText(value.toString());
+ }
+
+Q_SIGNALS:
+ void valueChanged(const QUrl &value);
+
+private Q_SLOTS:
+ inline void pressed()
+ {
+ auto path = QFileDialog::getOpenFileName(this);
+ if(!path.isEmpty())
+ m_lineEdit->setText(path);
+ }
+
+private:
+ QLineEdit *m_lineEdit;
+};
+
+class UrlCreator : public QItemEditorCreatorBase
+{
+public:
+ QWidget *createWidget(QWidget *parent) const Q_DECL_OVERRIDE
+ {
+ return new UrlWidget(parent);
+ }
+
+ QByteArray valuePropertyName() const Q_DECL_OVERRIDE
+ {
+ return "value";
+ }
+};
+
+class Matrix4x4Widget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QMatrix4x4 value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ inline Matrix4x4Widget(QWidget *parent = Q_NULLPTR) : QWidget(parent)
+ {
+ auto layout = new QGridLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_doubleSpinBox11 = new QDoubleSpinBox(this), 0, 0);
+ layout->addWidget(m_doubleSpinBox12 = new QDoubleSpinBox(this), 0, 1);
+ layout->addWidget(m_doubleSpinBox13 = new QDoubleSpinBox(this), 0, 2);
+ layout->addWidget(m_doubleSpinBox14 = new QDoubleSpinBox(this), 0, 3);
+ layout->addWidget(m_doubleSpinBox21 = new QDoubleSpinBox(this), 1, 0);
+ layout->addWidget(m_doubleSpinBox22 = new QDoubleSpinBox(this), 1, 1);
+ layout->addWidget(m_doubleSpinBox23 = new QDoubleSpinBox(this), 1, 2);
+ layout->addWidget(m_doubleSpinBox24 = new QDoubleSpinBox(this), 1, 3);
+ layout->addWidget(m_doubleSpinBox31 = new QDoubleSpinBox(this), 2, 0);
+ layout->addWidget(m_doubleSpinBox32 = new QDoubleSpinBox(this), 2, 1);
+ layout->addWidget(m_doubleSpinBox33 = new QDoubleSpinBox(this), 2, 2);
+ layout->addWidget(m_doubleSpinBox34 = new QDoubleSpinBox(this), 2, 3);
+ layout->addWidget(m_doubleSpinBox41 = new QDoubleSpinBox(this), 3, 0);
+ layout->addWidget(m_doubleSpinBox42 = new QDoubleSpinBox(this), 3, 1);
+ layout->addWidget(m_doubleSpinBox43 = new QDoubleSpinBox(this), 3, 2);
+ layout->addWidget(m_doubleSpinBox44 = new QDoubleSpinBox(this), 3, 3);
+ setLayout(layout);
+ }
+
+ inline QMatrix4x4 value() const
+ {
+ return QMatrix4x4(m_doubleSpinBox11->value(), m_doubleSpinBox12->value(), m_doubleSpinBox13->value(), m_doubleSpinBox14->value(),
+ m_doubleSpinBox21->value(), m_doubleSpinBox22->value(), m_doubleSpinBox23->value(), m_doubleSpinBox24->value(),
+ m_doubleSpinBox31->value(), m_doubleSpinBox32->value(), m_doubleSpinBox33->value(), m_doubleSpinBox34->value(),
+ m_doubleSpinBox41->value(), m_doubleSpinBox42->value(), m_doubleSpinBox43->value(), m_doubleSpinBox44->value());
+ }
+
+ inline void setValue(const QMatrix4x4 &value)
+ {
+ {
+ auto row = value.row(0);
+ m_doubleSpinBox11->setValue(row.x());
+ m_doubleSpinBox12->setValue(row.y());
+ m_doubleSpinBox13->setValue(row.z());
+ m_doubleSpinBox14->setValue(row.w());
+ }
+ {
+ auto row = value.row(1);
+ m_doubleSpinBox21->setValue(row.x());
+ m_doubleSpinBox22->setValue(row.y());
+ m_doubleSpinBox23->setValue(row.z());
+ m_doubleSpinBox24->setValue(row.w());
+ }
+ {
+ auto row = value.row(2);
+ m_doubleSpinBox31->setValue(row.x());
+ m_doubleSpinBox32->setValue(row.y());
+ m_doubleSpinBox33->setValue(row.z());
+ m_doubleSpinBox34->setValue(row.w());
+ }
+ {
+ auto row = value.row(3);
+ m_doubleSpinBox41->setValue(row.x());
+ m_doubleSpinBox42->setValue(row.y());
+ m_doubleSpinBox43->setValue(row.z());
+ m_doubleSpinBox44->setValue(row.w());
+ }
+ }
+
+Q_SIGNALS:
+ void valueChanged(const QMatrix4x4 &value);
+
+private:
+ QDoubleSpinBox *m_doubleSpinBox11, *m_doubleSpinBox12, *m_doubleSpinBox13, *m_doubleSpinBox14;
+ QDoubleSpinBox *m_doubleSpinBox21, *m_doubleSpinBox22, *m_doubleSpinBox23, *m_doubleSpinBox24;
+ QDoubleSpinBox *m_doubleSpinBox31, *m_doubleSpinBox32, *m_doubleSpinBox33, *m_doubleSpinBox34;
+ QDoubleSpinBox *m_doubleSpinBox41, *m_doubleSpinBox42, *m_doubleSpinBox43, *m_doubleSpinBox44;
+};
+
+class Matrix4x4Creator : public QItemEditorCreatorBase
+{
+public:
+ QWidget *createWidget(QWidget *parent) const Q_DECL_OVERRIDE
+ {
+ return new Matrix4x4Widget(parent);
+ }
+
+ QByteArray valuePropertyName() const Q_DECL_OVERRIDE
+ {
+ return "value";
+ }
+};
+
+class Vector2DWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector2D value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ inline Vector2DWidget(QWidget *parent = Q_NULLPTR) : QWidget(parent)
+ {
+ auto layout = new QHBoxLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_doubleSpinBoxX = new QDoubleSpinBox(this));
+ layout->addWidget(m_doubleSpinBoxY = new QDoubleSpinBox(this));
+ setLayout(layout);
+ }
+
+ inline QVector2D value() const
+ {
+ return QVector2D(m_doubleSpinBoxX->value(), m_doubleSpinBoxY->value());
+ }
+
+ inline void setValue(const QVector2D &value)
+ {
+ m_doubleSpinBoxX->setValue(value.x());
+ m_doubleSpinBoxY->setValue(value.y());
+ }
+
+Q_SIGNALS:
+ void valueChanged(const QVector2D &value);
+
+private:
+ QDoubleSpinBox *m_doubleSpinBoxX;
+ QDoubleSpinBox *m_doubleSpinBoxY;
+};
+
+class Vector2DCreator : public QItemEditorCreatorBase
+{
+public:
+ QWidget *createWidget(QWidget *parent) const Q_DECL_OVERRIDE
+ {
+ return new Vector2DWidget(parent);
+ }
+
+ QByteArray valuePropertyName() const Q_DECL_OVERRIDE
+ {
+ return "value";
+ }
+};
+
+class Vector3DWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector3D value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ inline Vector3DWidget(QWidget *parent = Q_NULLPTR) : QWidget(parent)
+ {
+ auto layout = new QHBoxLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_doubleSpinBoxX = new QDoubleSpinBox(this));
+ layout->addWidget(m_doubleSpinBoxY = new QDoubleSpinBox(this));
+ layout->addWidget(m_doubleSpinBoxZ = new QDoubleSpinBox(this));
+ setLayout(layout);
+ }
+
+ inline QVector3D value() const
+ {
+ return QVector3D(m_doubleSpinBoxX->value(), m_doubleSpinBoxY->value(), m_doubleSpinBoxZ->value());
+ }
+
+ inline void setValue(const QVector3D &value)
+ {
+ m_doubleSpinBoxX->setValue(value.x());
+ m_doubleSpinBoxY->setValue(value.y());
+ m_doubleSpinBoxZ->setValue(value.z());
+ }
+
+Q_SIGNALS:
+ void valueChanged(const QVector3D &value);
+
+private:
+ QDoubleSpinBox *m_doubleSpinBoxX;
+ QDoubleSpinBox *m_doubleSpinBoxY;
+ QDoubleSpinBox *m_doubleSpinBoxZ;
+};
+
+class Vector3DCreator : public QItemEditorCreatorBase
+{
+public:
+ QWidget *createWidget(QWidget *parent) const Q_DECL_OVERRIDE
+ {
+ return new Vector3DWidget(parent);
+ }
+
+ QByteArray valuePropertyName() const Q_DECL_OVERRIDE
+ {
+ return "value";
+ }
+};
+
+class Vector4DWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QVector4D value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ inline Vector4DWidget(QWidget *parent = Q_NULLPTR) : QWidget(parent)
+ {
+ auto layout = new QHBoxLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_doubleSpinBoxX = new QDoubleSpinBox(this));
+ layout->addWidget(m_doubleSpinBoxY = new QDoubleSpinBox(this));
+ layout->addWidget(m_doubleSpinBoxZ = new QDoubleSpinBox(this));
+ layout->addWidget(m_doubleSpinBoxW = new QDoubleSpinBox(this));
+ setLayout(layout);
+ }
+
+ inline QVector4D value() const
+ {
+ return QVector4D(m_doubleSpinBoxX->value(), m_doubleSpinBoxY->value(), m_doubleSpinBoxZ->value(), m_doubleSpinBoxW->value());
+ }
+
+ inline void setValue(const QVector4D &value)
+ {
+ m_doubleSpinBoxX->setValue(value.x());
+ m_doubleSpinBoxY->setValue(value.y());
+ m_doubleSpinBoxZ->setValue(value.z());
+ m_doubleSpinBoxW->setValue(value.w());
+ }
+
+Q_SIGNALS:
+ void valueChanged(const QVector4D &value);
+
+private:
+ QDoubleSpinBox *m_doubleSpinBoxX;
+ QDoubleSpinBox *m_doubleSpinBoxY;
+ QDoubleSpinBox *m_doubleSpinBoxZ;
+ QDoubleSpinBox *m_doubleSpinBoxW;
+};
+
+class Vector4DCreator : public QItemEditorCreatorBase
+{
+public:
+ QWidget *createWidget(QWidget *parent) const Q_DECL_OVERRIDE
+ {
+ return new Vector4DWidget(parent);
+ }
+
+ QByteArray valuePropertyName() const Q_DECL_OVERRIDE
+ {
+ return "value";
+ }
+};
+
+class QuaternionWidget : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(QQuaternion value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ inline QuaternionWidget(QWidget *parent = Q_NULLPTR) : QWidget(parent)
+ {
+ auto layout = new QHBoxLayout(this);
+ layout->setMargin(0);
+ layout->addWidget(m_doubleSpinBoxX = new QDoubleSpinBox(this));
+ layout->addWidget(m_doubleSpinBoxY = new QDoubleSpinBox(this));
+ layout->addWidget(m_doubleSpinBoxZ = new QDoubleSpinBox(this));
+ layout->addWidget(m_doubleSpinBoxScalar = new QDoubleSpinBox(this));
+ setLayout(layout);
+ }
+
+ inline QQuaternion value() const
+ {
+ return QQuaternion(m_doubleSpinBoxX->value(), m_doubleSpinBoxY->value(), m_doubleSpinBoxZ->value(), m_doubleSpinBoxScalar->value());
+ }
+
+ inline void setValue(const QQuaternion &value)
+ {
+ m_doubleSpinBoxX->setValue(value.x());
+ m_doubleSpinBoxY->setValue(value.y());
+ m_doubleSpinBoxZ->setValue(value.z());
+ m_doubleSpinBoxScalar->setValue(value.scalar());
+ }
+
+Q_SIGNALS:
+ void valueChanged(const QQuaternion &value);
+
+private:
+ QDoubleSpinBox *m_doubleSpinBoxX;
+ QDoubleSpinBox *m_doubleSpinBoxY;
+ QDoubleSpinBox *m_doubleSpinBoxZ;
+ QDoubleSpinBox *m_doubleSpinBoxScalar;
+};
+
+class QuaternionCreator : public QItemEditorCreatorBase
+{
+public:
+ QWidget *createWidget(QWidget *parent) const Q_DECL_OVERRIDE
+ {
+ return new QuaternionWidget(parent);
+ }
+
+ QByteArray valuePropertyName() const Q_DECL_OVERRIDE
+ {
+ return "value";
+ }
+};
+
+template
+class LimitedQSpinBox : public QSpinBox
+{
+public:
+ inline LimitedQSpinBox(QWidget *parent = Q_NULLPTR) : QSpinBox(parent)
+ {
+ setRange(Tmin, Tmax);
+ }
+};
+
+#endif // WIDGETS_H