[Development] [Interest] [Qt3D] Mixing C++ and QML

Svenn-Arne Dragly svenn-arne.dragly at qt.io
Mon Oct 30 09:51:38 CET 2017


>>> 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




More information about the Development mailing list