1634 outUniforms.clear();
1636 auto metaObject = m_owner->metaObject();
1639 const int propCount = metaObject->propertyCount();
1640 int propOffset = metaObject->propertyOffset();
1644 const QMetaObject *superClass = metaObject->superClass();
1645 while (superClass && qstrcmp(superClass->className(),
m_superClassName) != 0) {
1646 propOffset = superClass->propertyOffset();
1647 superClass = superClass->superClass();
1650 static auto getSamplerHint = [](
const QQuick3DTexture &texture) {
1651 if (
auto *po = QQuick3DObjectPrivate::get(&texture)) {
1652 if (po->type == QQuick3DObjectPrivate::Type::TextureProvider) {
1653 auto textureProvider =
static_cast<QQuick3DTextureProviderExtension *>(texture.textureProvider());
1654 switch (textureProvider->samplerHint()) {
1655 case QQuick3DTextureProviderExtension::SamplerHint::Sampler2D:
1656 return QSSGRenderSamplerType::Sampler2D;
1657 case QQuick3DTextureProviderExtension::SamplerHint::Sampler2DArray:
1658 return QSSGRenderSamplerType::Sampler2DArray;
1659 case QQuick3DTextureProviderExtension::SamplerHint::Sampler3D:
1660 return QSSGRenderSamplerType::Sampler3D;
1661 case QQuick3DTextureProviderExtension::SamplerHint::SamplerCube:
1662 return QSSGRenderSamplerType::SamplerCube;
1663 case QQuick3DTextureProviderExtension::SamplerHint::SamplerCubeArray:
1664 return QSSGRenderSamplerType::SamplerCubeArray;
1665 case QQuick3DTextureProviderExtension::SamplerHint::SamplerBuffer:
1666 return QSSGRenderSamplerType::SamplerBuffer;
1668 }
else if (po->type == QQuick3DObjectPrivate::Type::ImageCube) {
1669 return QSSGRenderSamplerType::SamplerCube;
1670 }
else if (texture.textureData() && texture.textureData()->depth() > 0) {
1671 return QSSGRenderSamplerType::Sampler3D;
1675 return QSSGRenderSamplerType::Sampler2D;
1678 const auto addTextureToUniforms = [&](
const char *name, QQuick3DTexture *texture,
int propertyIndex) {
1679 QSSGRenderImage *ri =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(texture)->spatialNode);
1680 auto samplerName = QSSGBaseTypeHelpers::toString(getSamplerHint(*texture));
1681 outUniforms.emplace_back(name, samplerName, QVariant::fromValue(ri), QSSGRenderShaderValue::Texture, propertyIndex);
1685 const auto addTextureInputWatchers = [&](QMetaProperty property, QQuick3DShaderUtilsTextureInput *textureInput) {
1686 QObject::connect(textureInput, &QQuick3DShaderUtilsTextureInput::enabledChanged, m_owner, [
this, property, textureInput](){ addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput); }, Qt::UniqueConnection);
1687 QObject::connect(textureInput, &QQuick3DShaderUtilsTextureInput::textureChanged, m_owner, [
this, property, textureInput](){ addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput); }, Qt::UniqueConnection);
1688 if (
auto *texture = textureInput->texture())
1689 addTextureToUniforms(property.name(), texture, property.propertyIndex());
1692 for (
int i = propOffset; i != propCount; ++i) {
1693 const QMetaProperty property = metaObject->property(i);
1694 if (Q_UNLIKELY(!property.isValid()))
1697 const char *name = property.name();
1698 QMetaType propType = property.metaType();
1699 QVariant propValue = property.read(m_owner);
1700 if (propType == QMetaType(QMetaType::QVariant))
1701 propType = propValue.metaType();
1703 const auto type = QSSGShaderUtils::uniformType(propType);
1704 if (type != QSSGRenderShaderValue::Unknown) {
1705 outUniforms.emplace_back(name, QSSGShaderUtils::uniformTypeName(propType),
1706 propValue, QSSGShaderUtils::uniformType(propType), i);
1707 addPropertyWatcher(property, DirtyPropertyHint::Value);
1709 if (propType.id() >= QMetaType::User) {
1710 if (propType.id() == qMetaTypeId<QQuick3DTexture *>()) {
1711 if (QQuick3DTexture *texture = property.read(m_owner).value<QQuick3DTexture *>()) {
1712 addTextureToUniforms(name, texture, i);
1713 addPropertyWatcher(property, DirtyPropertyHint::Reference, texture);
1715 }
else if (propType.id() == qMetaTypeId<QQuick3DShaderUtilsTextureInput *>()) {
1716 if (QQuick3DShaderUtilsTextureInput *textureInput = property.read(m_owner).value<QQuick3DShaderUtilsTextureInput *>(); textureInput && textureInput->texture()) {
1717 addTextureInputWatchers(property, textureInput);
1718 addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput);
1721 }
else if (propType == QMetaType(QMetaType::QObjectStar)) {
1722 if (QQuick3DTexture *texture = qobject_cast<QQuick3DTexture *>(propValue.value<QObject *>())) {
1723 addTextureToUniforms(name, texture, i);
1724 addPropertyWatcher(property, DirtyPropertyHint::Reference, texture);
1725 }
else if (QQuick3DShaderUtilsTextureInput *textureInput = qobject_cast<QQuick3DShaderUtilsTextureInput *>(propValue.value<QObject *>()); textureInput && textureInput->texture()) {
1726 addTextureInputWatchers(property, textureInput);
1727 addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput);
1736 if (property.isValid() && property.hasNotifySignal()) {
1738 const auto pid = property.propertyIndex();
1739 Q_ASSERT(pid != -1);
1740 auto it = std::find_if(m_trackedProperties.begin(), m_trackedProperties.end(), [pid](
const Tracked &tp) {
return tp.pid == pid; });
1741 const bool found = (it != m_trackedProperties.end());
1742 QQuick3DObject *oldObj =
nullptr;
1745 m_trackedProperties.push_back({watcher, object, pid});
1746 it = std::prev(m_trackedProperties.end());
1748 oldObj = it->object;
1749 it->object = object;
1753 const auto &sm = QQuick3DObjectPrivate::get(m_owner)->sceneManager;
1756 const bool changed = (oldObj != object);
1759 if (changed && oldObj) {
1760 QQuick3DObjectPrivate::get(oldObj)->derefSceneManager();
1761 QObject::disconnect(oldObj, &QObject::destroyed, m_owner,
nullptr);
1765 if (changed && object) {
1766 QQuick3DObjectPrivate::get(object)->refSceneManager(*sm);
1767 QObject::connect(object, &QObject::destroyed, m_owner, [
this, property](QObject *obj) {
1769 addPropertyWatcher(property, DirtyPropertyHint::Reference,
nullptr);
1774 markTrackedPropertyDirty(property, hint);