Re: [Development] [Interest] [Qt3D] Mixing C++ and QML
A typical pattern in QtQuick is that a QQmlListProperty is the default property, so declared children are automatically added. But instead you have to declare the Components first, and then also add them to a vector. Why is that? It seems needlessly cumbersome to me. If Components are naturally always children of Entities, ^ that is your broken assumption. Components do not have to be children of the entity. We actually started out with that but found that it prohibits sharing components which can sometimes be handy. “sometimes”… so maybe add declared child Components to the vector automatically, but also allow sharing them by ID when necessary? I would rather say "often" than "sometimes" for this one. In simple examples, each component is often used only in one entity, but in more realistic use cases, components like materials tend to be shared. While I would also prefer a solution that "just works" when you add components as children to an entity, I think this is hard to get right. The naive solution is to allow both uses and just add them to the parent's vector, but because you would typically add shared components as children of some root component, this would end up drawing the root entity as a mix of all shared components in addition to the entities using those components. I.e., this would draw the mesh three times: Entity { id: root Mesh { id: mesh } Material { id: material } Transform { id: transform1 } Transform { id: transform2 } Entity { components: [ transform1, material, mesh ] } Entity { components: [ transform2, material, mesh ] } } To work around that issue, we could detect any sharing of components and remove it from its parent if it's shared, but this seems like a bad solution in my opinion. Alternatively, we could add `shared` property to each component that should not be added to its parent's vector: Entity { id: root Mesh { id: mesh; shared: true } Material { id: material; shared: true } Transform { id: transform1; shared: true } Transform { id: transform2; shared: true } Entity { components: [ transform1, material, mesh ] } Entity { components: [ transform2, material, mesh ] } } Or we could introduce some new node that isn't an Entity and can hold the shared components, while any component added as a child to an entity becomes added to the parent's vector: Entity { id: root SharedComponents { Mesh { id: mesh } Material { id: material } Transform { id: transform1 } Transform { id: transform2 } } Entity { components: [ transform1, material, mesh ] } Entity { components: [ transform2, material, mesh ] } } I think last option is the best of the three, but there might be better alternatives. And neither is much better than the current API, in my opinion. Svenn-Arne ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [Interest] [Qt3D] Mixing C++ and QML
> On 20 Oct 2017, at 12:33, Sean Harmerwrote: > > Hi, > > On 19/10/2017 19:44, Shawn Rutledge wrote: >> >> What exactly do you think should be done there, in case we can fix it >> some day? > > Probably something like how NSObject manages properties of collections. So > far with Qt3D we've only needed the same level of semantics as offered by > QQmlListProperty - or rather we've worked within those constraints. So a > simple indexed container with the ability to add/remove items. > > In a more general setting I can easily also imagine support for associative > containers too. We have dynamic properties at least. > The tricky part will be deciding which semantics do we wish to support and > where do we draw the line between such properties and recommending to use a > full-blown model instead. > > Speaking of which, improving QAIM to be able to return data for contiguous > blocks of indices in one function call would be a really welcome addition. > Calling so many virtuals to retrieve a single data value for a single index > and role is not exactly efficient. The existing QAIM API is fine for the > existing views but doesn't scale well when trying to use them to populate, > say a buffer of per instance data on a large scale. Yes I know we could avoid > this with custom API but users have so many models at this point it would be > nice to offer some interoperability with them. So you want something like QVector dataRows(const QModelIndex , int rows, int role = Qt::DisplayRole)? It’s been pointed out as somewhat of a bottleneck (for QtQuick applications at least) that data() returns QVariant. But what sort of alternative is there for C++ API? >> A typical pattern in QtQuick is that a QQmlListProperty is the >> default property, so declared children are automatically added. But >> instead you have to declare the Components first, and then also add >> them to a vector. Why is that? It seems needlessly cumbersome to >> me. If Components are naturally always children of Entities, > > ^ that is your broken assumption. Components do not have to be children of > the entity. We actually started out with that but found that it prohibits > sharing components which can sometimes be handy. “sometimes”… so maybe add declared child Components to the vector automatically, but also allow sharing them by ID when necessary? > Also whilst I'm here, there's an annoying limitation in the QML language that > prevents mixing inline declaration of elements with elements referenced by id > in a list property. That is you cannot write something like: > > Mesh { id: mesh } > Material { id: material } > > Entity { >components: [ Transform {}, material, mesh ] > } Is there a bug written up about that one? >> If you think there’s something wrong with the normal QObject >> parent/child relationship, then there’s another mechanism for >> detecting declared QML “children" and doing “something special” with >> them. > > Do you mean the autoparent callback? > > http://code.qt.io/cgit/qt/qt3d.git/tree/src/quick3d/quick3d/qt3dquick_global.cpp#n676 > > We need this here because it's not enough for us to know that the parent is a > QObject. We need to know if it's a QNode to be able to add the new child to > the scene. OK, it calls setParent but does not add it to the components vector. > One possible future solution we discussed with Lars and Simon for this is to > make QObjectPrivate::setParent() virtual. Yeah that might work, but has a pervasive cost I suppose. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [Interest] [Qt3D] Mixing C++ and QML
On 20/10/2017 09:06, Pierre-Yves Siret wrote: 2017-10-19 20:44 GMT+02:00 Shawn Rutledge>: (thread started on the interest list, but I don’t think my comments belong there) On Oct 19, 2017, at 18:06, Sean Harmer > wrote: > Hi, > > you've hit one of the issues we did with exposing C++ and QML APIs. Namely, QQmlListProperty. This thing should ideally never have existed and instead support for properties of collections should have been added to QObject and the metaobject system. What exactly do you think should be done there, in case we can fix it some day? QObjects are normally managed as a tree for memory management purposes, so I’ve also long disliked the fact that it doesn’t quite match the nesting of the Item declarations in QML, because of the separate QList childItems. It’s confusing and wastes memory. QQmlListProperty is flexible about storage, since you get to write all the accessors, so you can maybe use it just for QML and also have normal C++ API? I have some gripes about QQmlListProperty too, maybe not the same ones. I agree that having a QQmlListProperty in a class supposed to be used from c++ looks alien. Even worse, it pulls in a dependency on the QtQml module. Having it supported in the meta object sure looks enticing at a first view. Maybe with something like Q_LIST_PROPERTY(ElementType list GET getFunction COUNT countFunction ...). That ends up being quite like a simplified QAIM without the roles and the signals. Exactly, where to draw the line between simple properties of collections and full-blown models? Cheers, Sean -- Dr Sean Harmer | sean.har...@kdab.com | Managing Director UK KDAB (UK) Ltd, a KDAB Group company Tel. +44 (0)1625 809908; Sweden (HQ) +46-563-540090 Mobile: +44 (0)7545 140604 KDAB - Qt Experts ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [Interest] [Qt3D] Mixing C++ and QML
Hi, On 19/10/2017 19:44, Shawn Rutledge wrote: (thread started on the interest list, but I don’t think my comments belong there) On Oct 19, 2017, at 18:06, Sean Harmerwrote: Hi, you've hit one of the issues we did with exposing C++ and QML APIs. Namely, QQmlListProperty. This thing should ideally never have existed and instead support for properties of collections should have been added to QObject and the metaobject system. What exactly do you think should be done there, in case we can fix it some day? Probably something like how NSObject manages properties of collections. So far with Qt3D we've only needed the same level of semantics as offered by QQmlListProperty - or rather we've worked within those constraints. So a simple indexed container with the ability to add/remove items. In a more general setting I can easily also imagine support for associative containers too. The tricky part will be deciding which semantics do we wish to support and where do we draw the line between such properties and recommending to use a full-blown model instead. Speaking of which, improving QAIM to be able to return data for contiguous blocks of indices in one function call would be a really welcome addition. Calling so many virtuals to retrieve a single data value for a single index and role is not exactly efficient. The existing QAIM API is fine for the existing views but doesn't scale well when trying to use them to populate, say a buffer of per instance data on a large scale. Yes I know we could avoid this with custom API but users have so many models at this point it would be nice to offer some interoperability with them. QObjects are normally managed as a tree for memory management purposes, so I’ve also long disliked the fact that it doesn’t quite match the nesting of the Item declarations in QML, because of the separate QList childItems. It’s confusing and wastes memory. We avoided that in Qt 3D and just use the regular parent-child relationship. We don't have separation between visual parent and QObject parent. QQmlListProperty is flexible about storage, since you get to write all the accessors, so you can maybe use it just for QML and also have normal C++ API? That's what we did. The C++ API has addComponent(), removeComponent(), componentCount() type functions, and then we have libraries sat on top for each aspect that add in the QQmlListProperty handling via extension objects. For e.g. http://code.qt.io/cgit/qt/qt3d.git/tree/src/quick3d/quick3drender A typical pattern in QtQuick is that a QQmlListProperty is the default property, so declared children are automatically added. But instead you have to declare the Components first, and then also add them to a vector. Why is that? It seems needlessly cumbersome to me. If Components are naturally always children of Entities, ^ that is your broken assumption. Components do not have to be children of the entity. We actually started out with that but found that it prohibits sharing components which can sometimes be handy. then it ought to be enough to declare them inside an Entity. But it seems that any QNode can have any number of QNode children, so maybe you could have a QQmlListPropery as the default property, whose implementation uses the QObject children, just for convenience in QML? Also whilst I'm here, there's an annoying limitation in the QML language that prevents mixing inline declaration of elements with elements referenced by id in a list property. That is you cannot write something like: Mesh { id: mesh } Material { id: material } Entity { components: [ Transform {}, material, mesh ] } If you think there’s something wrong with the normal QObject parent/child relationship, then there’s another mechanism for detecting declared QML “children" and doing “something special” with them. Do you mean the autoparent callback? http://code.qt.io/cgit/qt/qt3d.git/tree/src/quick3d/quick3d/qt3dquick_global.cpp#n676 We need this here because it's not enough for us to know that the parent is a QObject. We need to know if it's a QNode to be able to add the new child to the scene. One possible future solution we discussed with Lars and Simon for this is to make QObjectPrivate::setParent() virtual. We use it to make each Window transient for whatever Window or Item’s window that it was declared inside of, for adding PointerHandlers to Items, and stuff like that: any case where one object can be declared inside another, but it’s not quite a conventional parent/child relationship, for example because the “parent” and “child” aren’t the same kind of objects. Either of those mechanisms can keep the syntax nice in QML. To avoid pulling in a QtQml dependency in the C++ API, we instead have another layer to add the QML specifics (pretty much entirely list properties). Ugh that would indeed be nice to simplify. In order to create these from code we have a
Re: [Development] [Interest] [Qt3D] Mixing C++ and QML
2017-10-19 20:44 GMT+02:00 Shawn Rutledge: > (thread started on the interest list, but I don’t think my comments belong > there) > > On Oct 19, 2017, at 18:06, Sean Harmer wrote: > > > Hi, > > > > you've hit one of the issues we did with exposing C++ and QML APIs. > Namely, QQmlListProperty. This thing should ideally never have existed and > instead support for properties of collections should have been added to > QObject and the metaobject system. > > What exactly do you think should be done there, in case we can fix it some > day? > > QObjects are normally managed as a tree for memory management purposes, so > I’ve also long disliked the fact that it doesn’t quite match the nesting of > the Item declarations in QML, because of the separate QList > childItems. It’s confusing and wastes memory. > > QQmlListProperty is flexible about storage, since you get to write all the > accessors, so you can maybe use it just for QML and also have normal C++ > API? > I have some gripes about QQmlListProperty too, maybe not the same ones. I agree that having a QQmlListProperty in a class supposed to be used from c++ looks alien. Having it supported in the meta object sure looks enticing at a first view. Maybe with something like Q_LIST_PROPERTY(ElementType list GET getFunction COUNT countFunction ...). That ends up being quite like a simplified QAIM without the roles and the signals. My other wish would be to be able to populate a QQmlListProperty from a model, and the general lack of support for models in the QML world (caused by the need to explicitly add support for models for your types) For example how do I add series from a model in a ChartView ? (this is embarrassing for what should be a data driven component) How can I populate the new Shape type from a model ? etc. Some types add explicit support for models, MapItemView for example, but this seems to be hard. Look at all the bugs related to MapItemView in the bug tracker (sorry Paolo, it's the first one that came to mind, I don't mean to be mean ;) ). And if you eventually manage to do it correctly, you still don't support dumb models like js array, integer, stringlist... You'll have to bring it complicated private stuff for it. ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development
Re: [Development] [Interest] [Qt3D] Mixing C++ and QML
(thread started on the interest list, but I don’t think my comments belong there) On Oct 19, 2017, at 18:06, Sean Harmerwrote: > Hi, > > you've hit one of the issues we did with exposing C++ and QML APIs. Namely, > QQmlListProperty. This thing should ideally never have existed and instead > support for properties of collections should have been added to QObject and > the metaobject system. What exactly do you think should be done there, in case we can fix it some day? QObjects are normally managed as a tree for memory management purposes, so I’ve also long disliked the fact that it doesn’t quite match the nesting of the Item declarations in QML, because of the separate QList childItems. It’s confusing and wastes memory. QQmlListProperty is flexible about storage, since you get to write all the accessors, so you can maybe use it just for QML and also have normal C++ API? A typical pattern in QtQuick is that a QQmlListProperty is the default property, so declared children are automatically added. But instead you have to declare the Components first, and then also add them to a vector. Why is that? It seems needlessly cumbersome to me. If Components are naturally always children of Entities, then it ought to be enough to declare them inside an Entity. But it seems that any QNode can have any number of QNode children, so maybe you could have a QQmlListPropery as the default property, whose implementation uses the QObject children, just for convenience in QML? If you think there’s something wrong with the normal QObject parent/child relationship, then there’s another mechanism for detecting declared QML “children" and doing “something special” with them. We use it to make each Window transient for whatever Window or Item’s window that it was declared inside of, for adding PointerHandlers to Items, and stuff like that: any case where one object can be declared inside another, but it’s not quite a conventional parent/child relationship, for example because the “parent” and “child” aren’t the same kind of objects. Either of those mechanisms can keep the syntax nice in QML. > To avoid pulling in a QtQml dependency in the C++ API, we instead have > another layer to add the QML specifics (pretty much entirely list properties). Ugh that would indeed be nice to simplify. > In order to create these from code we have a factory. Try something like: > > QAbstractNodeFactory::createNode("QEntity") > > If using just C++ you will get a standard QEntity. If using QML (and the > types are registered with the factory) you will get the QML -enhanced version > with the extension object that handles the list properties. If we had collection properties in QObject somehow, would you get rid of the factories? Or everything is stuck in place now because of having public API? ___ Development mailing list Development@qt-project.org http://lists.qt-project.org/mailman/listinfo/development