1725 outUniforms.clear();
1727 auto metaObject = m_owner->metaObject();
1730 const int propCount = metaObject->propertyCount();
1731 int propOffset = metaObject->propertyOffset();
1735 const QMetaObject *superClass = metaObject->superClass();
1736 while (superClass && qstrcmp(superClass->className(),
m_superClassName) != 0) {
1737 propOffset = superClass->propertyOffset();
1738 superClass = superClass->superClass();
1741 static auto getSamplerHint = [](
const QQuick3DTexture &texture) {
1742 if (
auto *po = QQuick3DObjectPrivate::get(&texture)) {
1743 if (po->type == QQuick3DObjectPrivate::Type::TextureProvider) {
1744 auto textureProvider =
static_cast<QQuick3DTextureProviderExtension *>(texture.textureProvider());
1745 switch (textureProvider->samplerHint()) {
1746 case QQuick3DTextureProviderExtension::SamplerHint::Sampler2D:
1747 return QSSGRenderSamplerType::Sampler2D;
1748 case QQuick3DTextureProviderExtension::SamplerHint::Sampler2DArray:
1749 return QSSGRenderSamplerType::Sampler2DArray;
1750 case QQuick3DTextureProviderExtension::SamplerHint::Sampler3D:
1751 return QSSGRenderSamplerType::Sampler3D;
1752 case QQuick3DTextureProviderExtension::SamplerHint::SamplerCube:
1753 return QSSGRenderSamplerType::SamplerCube;
1754 case QQuick3DTextureProviderExtension::SamplerHint::SamplerCubeArray:
1755 return QSSGRenderSamplerType::SamplerCubeArray;
1756 case QQuick3DTextureProviderExtension::SamplerHint::SamplerBuffer:
1757 return QSSGRenderSamplerType::SamplerBuffer;
1759 }
else if (po->type == QQuick3DObjectPrivate::Type::ImageCube) {
1760 return QSSGRenderSamplerType::SamplerCube;
1761 }
else if (texture.textureData() && texture.textureData()->depth() > 0) {
1762 return QSSGRenderSamplerType::Sampler3D;
1766 return QSSGRenderSamplerType::Sampler2D;
1769 const auto addTextureToUniforms = [&](
const char *name, QQuick3DTexture *texture,
int propertyIndex) {
1770 QSSGRenderImage *ri =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(texture)->spatialNode);
1771 auto samplerName = QSSGBaseTypeHelpers::toString(getSamplerHint(*texture));
1772 outUniforms.emplace_back(name, samplerName, QVariant::fromValue(ri), QSSGRenderShaderValue::Texture, propertyIndex);
1776 const auto addTextureInputWatchers = [&](QMetaProperty property, QQuick3DShaderUtilsTextureInput *textureInput) {
1777 QObject::connect(textureInput, &QQuick3DShaderUtilsTextureInput::enabledChanged, m_owner, [
this, property, textureInput](){ addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput); }, Qt::UniqueConnection);
1778 QObject::connect(textureInput, &QQuick3DShaderUtilsTextureInput::textureChanged, m_owner, [
this, property, textureInput](){ addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput); }, Qt::UniqueConnection);
1779 if (
auto *texture = textureInput->texture())
1780 addTextureToUniforms(property.name(), texture, property.propertyIndex());
1783 for (
int i = propOffset; i != propCount; ++i) {
1784 const QMetaProperty property = metaObject->property(i);
1785 if (Q_UNLIKELY(!property.isValid()))
1788 const char *name = property.name();
1789 QMetaType propType = property.metaType();
1790 QVariant propValue = property.read(m_owner);
1791 if (propType == QMetaType(QMetaType::QVariant))
1792 propType = propValue.metaType();
1794 const auto type = QSSGShaderUtils::uniformType(propType);
1795 if (type != QSSGRenderShaderValue::Unknown) {
1796 outUniforms.emplace_back(name, QSSGShaderUtils::uniformTypeName(propType),
1797 propValue, QSSGShaderUtils::uniformType(propType), i);
1798 addPropertyWatcher(property, DirtyPropertyHint::Value);
1800 if (propType.id() >= QMetaType::User) {
1801 if (propType.id() == qMetaTypeId<QQuick3DTexture *>()) {
1802 if (QQuick3DTexture *texture = property.read(m_owner).value<QQuick3DTexture *>()) {
1803 addTextureToUniforms(name, texture, i);
1804 addPropertyWatcher(property, DirtyPropertyHint::Reference, texture);
1806 }
else if (propType.id() == qMetaTypeId<QQuick3DShaderUtilsTextureInput *>()) {
1807 if (QQuick3DShaderUtilsTextureInput *textureInput = property.read(m_owner).value<QQuick3DShaderUtilsTextureInput *>(); textureInput && textureInput->texture()) {
1808 addTextureInputWatchers(property, textureInput);
1809 addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput);
1812 }
else if (propType == QMetaType(QMetaType::QObjectStar)) {
1813 if (QQuick3DTexture *texture = qobject_cast<QQuick3DTexture *>(propValue.value<QObject *>())) {
1814 addTextureToUniforms(name, texture, i);
1815 addPropertyWatcher(property, DirtyPropertyHint::Reference, texture);
1816 }
else if (QQuick3DShaderUtilsTextureInput *textureInput = qobject_cast<QQuick3DShaderUtilsTextureInput *>(propValue.value<QObject *>()); textureInput && textureInput->texture()) {
1817 addTextureInputWatchers(property, textureInput);
1818 addPropertyWatcher(property, DirtyPropertyHint::Reference, textureInput);
1827 if (property.isValid() && property.hasNotifySignal()) {
1829 const auto pid = property.propertyIndex();
1830 Q_ASSERT(pid != -1);
1831 auto it = std::find_if(m_trackedProperties.begin(), m_trackedProperties.end(), [pid](
const Tracked &tp) {
return tp.pid == pid; });
1832 const bool found = (it != m_trackedProperties.end());
1833 QQuick3DObject *oldObj =
nullptr;
1836 m_trackedProperties.push_back({watcher, object, pid});
1837 it = std::prev(m_trackedProperties.end());
1839 oldObj = it->object;
1840 it->object = object;
1844 const auto &sm = QQuick3DObjectPrivate::get(m_owner)->sceneManager;
1847 const bool changed = (oldObj != object);
1850 if (changed && oldObj) {
1851 QQuick3DObjectPrivate::get(oldObj)->derefSceneManager();
1852 QObject::disconnect(oldObj, &QObject::destroyed, m_owner,
nullptr);
1856 if (changed && object) {
1857 QQuick3DObjectPrivate::get(object)->refSceneManager(*sm);
1858 QObject::connect(object, &QObject::destroyed, m_owner, [
this, property](QObject *obj) {
1860 addPropertyWatcher(property, DirtyPropertyHint::Reference,
nullptr);
1865 markTrackedPropertyDirty(property, hint);