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 + + + + + + + 0 + 0 + 1024 + 17 + + + + + &File + + + + + + + + + + + &Edit + + + + + + + + + + + &Game + + + + + + + + + + + + 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