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

Reply via email to