Kuesa Iro-Materials-Gallery QML Example
#include "materialinspector.h"
#include <Kuesa/GLTF2Material>
#include <Kuesa/GLTF2MaterialProperties>
#include <Qt3DRender/QMaterial>
#include <Qt3DRender/QPickEvent>
#include <Qt3DRender/QAbstractTexture>
#include <Qt3DCore/QEntity>
#include <Qt3DCore/QComponent>
#include <QDebug>
#include <QMetaProperty>
#include <QVector2D>
#include <QVector3D>
#include <QVector4D>
namespace {
template<typename ComponentType>
inline ComponentType *componentFromEntity(Qt3DCore::QEntity *e)
{
const auto cmps = e->componentsOfType<ComponentType>();
return cmps.size() > 0 ? cmps.first() : nullptr;
}
template<typename ComponentType>
ComponentType *findFirstComponentInstanceInHierarchy(Qt3DCore::QEntity *root)
{
ComponentType *cmp = componentFromEntity<ComponentType>(root);
if (cmp)
return cmp;
const Qt3DCore::QNodeVector children = root->childNodes();
for (Qt3DCore::QNode *child : children) {
Qt3DCore::QEntity *e = qobject_cast<Qt3DCore::QEntity *>(child);
if (e) {
cmp = findFirstComponentInstanceInHierarchy<ComponentType>(e);
if (cmp)
return cmp;
}
}
return nullptr;
}
QString valueIntrospector(const QVariant &value)
{
switch (value.userType()) {
case QVariant::Bool:
return value.toBool() ? QStringLiteral("true") : QStringLiteral("false");
case QVariant::Double:
case QMetaType::Float:
return QString::number(value.toDouble());
case QVariant::Int:
case QVariant::UInt:
return QString::number(value.toInt());
case QVariant::Color: {
const QColor color = value.value<QColor>();
return QString("[%1, %2, %3, %4]")
.arg(color.redF())
.arg(color.greenF())
.arg(color.blueF())
.arg(color.alphaF());
}
case QVariant::Vector2D: {
const QVector2D v2 = value.value<QVector2D>();
return QString("[%1, %2]")
.arg(v2.x())
.arg(v2.y());
}
case QVariant::Vector3D: {
const QVector3D v3 = value.value<QVector3D>();
return QString("[%1, %2, %3]")
.arg(v3.x())
.arg(v3.y())
.arg(v3.z());
}
case QVariant::Vector4D: {
const QVector4D v4 = value.value<QVector4D>();
return QString("[%1, %2, %3, %4]")
.arg(v4.x())
.arg(v4.y())
.arg(v4.z())
.arg(v4.w());
}
case QVariant::Matrix4x4:
return QString("Matrix");
}
if (value.userType() == qMetaTypeId<Qt3DRender::QAbstractTexture *>()) {
return QStringLiteral("Texture");
}
return QStringLiteral("Unknown");
}
}
MaterialInspector::MaterialInspector(QObject *parent)
: QObject(parent)
, m_material(nullptr)
{
}
Kuesa::GLTF2Material *MaterialInspector::material() const
{
return m_material;
}
QString MaterialInspector::description() const
{
return m_description;
}
void MaterialInspector::inspect(Qt3DRender::QPickEvent *pick)
{
Qt3DCore::QEntity *entity = pick->entity();
if (entity == nullptr) {
setMaterial(nullptr);
return;
}
Kuesa::GLTF2Material *material = findFirstComponentInstanceInHierarchy<Kuesa::GLTF2Material>(entity);
setMaterial(material);
}
void MaterialInspector::setMaterial(Kuesa::GLTF2Material *material)
{
if (m_material == material)
return;
m_material = material;
emit materialChanged();
introspect();
}
void MaterialInspector::introspect()
{
m_description.clear();
if (m_material) {
Kuesa::GLTF2MaterialProperties *materialProperties = nullptr;
const QMetaObject *materialMetaObj = m_material->metaObject();
QString descriptionString = QString("%1:\n").arg(materialMetaObj->className());
QString propertyDescription = QString("%1: %2\n");
const int materialPropertiesIdx = materialMetaObj->indexOfProperty("materialProperties");
if (materialPropertiesIdx != -1) {
materialProperties = m_material->property("materialProperties").value<Kuesa::GLTF2MaterialProperties *>();
const QMetaObject *propertiesMetaObj = materialProperties->metaObject();
const int defaultPropertiesOffset = 5;
for (int i = defaultPropertiesOffset, m = propertiesMetaObj->propertyCount(); i < m; ++i) {
const QMetaProperty metaProp = propertiesMetaObj->property(i);
descriptionString += propertyDescription.arg(metaProp.name(), valueIntrospector(metaProp.read(materialProperties)));
}
}
m_description = descriptionString;
}
emit descriptionChanged();
}