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

2017-10-30 Thread Svenn-Arne Dragly



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

2017-10-20 Thread Shawn Rutledge

> On 20 Oct 2017, at 12:33, Sean Harmer  wrote:
> 
> 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

2017-10-20 Thread Sean Harmer



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

2017-10-20 Thread Sean Harmer

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


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-20 Thread Pierre-Yves Siret
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

2017-10-19 Thread 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?

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