Example #1
0
void QCollisionAspect::sceneNodeAdded(QSceneChangePtr &e)
{
    QScenePropertyChangePtr propertyChange = e.staticCast<QScenePropertyChange>();
    QNodePtr nodePtr = propertyChange->value().value<QNodePtr>();
    QNode *n = nodePtr.data();
    QNodeVisitor visitor;
    visitor.traverse(n, this, &QCollisionAspect::visitNode);
}
Example #2
0
File: qnode.cpp Project: RSATom/Qt
/*!
 * \internal
 *
 * Called by _q_setParentHelper() or _q_postConstructorInit()
 * on the main thread.
 */
void QNodePrivate::_q_addChild(QNode *childNode)
{
    Q_ASSERT(childNode);
    Q_ASSERT_X(childNode->parent() == q_func(), Q_FUNC_INFO,  "not a child of this node");

    // Have we already notified the parent about its new child? If so, bail out
    // early so that we do not send more than one new child event to the backend
    QNodePrivate *childD = QNodePrivate::get(childNode);
    if (childD->m_notifiedParent == true)
        return;

    // Store our id as the parentId in the child so that even if the child gets
    // removed from the scene as part of the destruction of the parent, when the
    // parent's children are deleted in the QObject dtor, we still have access to
    // the parentId. If we didn't store this, we wouldn't have access at that time
    // because the parent would then only be a QObject, the QNode part would have
    // been destroyed already.
    childD->m_parentId = m_id;

    if (!m_scene)
        return;

    // We need to send a QPropertyNodeAddedChange to the backend
    // to notify the backend that we have a new child
    if (m_changeArbiter != nullptr) {
        // Flag that we have notified the parent. We do this immediately before
        // creating the change because that recurses back into this function and
        // we need to catch that to avoid sending more than one new child event
        // to the backend.
        childD->m_notifiedParent = true;
        const auto change = QPropertyNodeAddedChangePtr::create(m_id, childNode);
        change->setPropertyName("children");
        notifyObservers(change);
    }

    // Update the scene
    // TODO: Fold this into the QNodeCreatedChangeGenerator so we don't have to
    // traverse the sub tree three times!
    QNodeVisitor visitor;
    visitor.traverse(childNode, this, &QNodePrivate::addEntityComponentToScene);
}
Example #3
0
File: qnode.cpp Project: RSATom/Qt
/*!
 * \internal
 *
 * Notify the backend that the parent lost this node as a child and
 * that this node is being destroyed. We only send the node removed
 * change for the parent's children property iff we have an id for
 * a parent node. This is set/unset in the _q_addChild()/_q_removeChild()
 * functions (and initialized in init() if there is a parent at
 * construction time).
 *
 * Likewise, we only send the node destroyed change, iff we have
 * previously sent a node created change. This is tracked via the
 * m_hasBackendNode member.
 */
void QNodePrivate::notifyDestructionChangesAndRemoveFromScene()
{
    Q_Q(QNode);

    // We notify the backend that the parent lost us as a child
    if (m_changeArbiter != nullptr && !m_parentId.isNull()) {
        const auto change = QPropertyNodeRemovedChangePtr::create(m_parentId, q);
        change->setPropertyName("children");
        notifyObservers(change);
    }

    // Tell the backend we are about to be destroyed
    if (m_hasBackendNode) {
        const QDestructionIdAndTypeCollector collector(q);
        const auto destroyedChange = QNodeDestroyedChangePtr::create(q, collector.subtreeIdsAndTypes());
        notifyObservers(destroyedChange);
    }

    // We unset the scene from the node as its backend node was/is about to be destroyed
    QNodeVisitor visitor;
    visitor.traverse(q, this, &QNodePrivate::unsetSceneHelper);
}
Example #4
0
File: qnode.cpp Project: RSATom/Qt
/*!
 * \internal
 *
 * Reparents the public QNode to \a parent. If the new parent is nullptr then this
 * QNode is no longer part of the scene and so we notify the backend of its removal
 * from its parent's list of children, and then send a QNodeDestroyedChange to the
 * aspects so that the corresponding backend node is destroyed.
 *
 * If \a parent is not null, then we must tell its new parent about this QNode now
 * being a child of it on the backend. If this QNode did not have a parent upon
 * entry to this function, then we must first send a QNodeCreatedChange to the backend
 * prior to sending the QPropertyNodeAddedChange to its parent.
 *
 * Note: This function should never be called from the ctor directly as the type may
 * not be fully created yet and creating creation changes involves calling a virtual
 * function on QNode. The function _q_notifyCreationAndChildChanges() is used
 * for sending initial notification when a parent is passed to the QNode ctor.
 * That function does a subset of this function with the assumption that the new object
 * had no parent before (must be true as it is newly constructed).
 */
void QNodePrivate::_q_setParentHelper(QNode *parent)
{
    Q_Q(QNode);
    QNode *oldParentNode = q->parentNode();

    // We may get the situation where the QML engine has set the QObject
    // parent but we have not yet set up the QNode parent requirements.
    // This check handles this and means we propagate the scene and arbiter
    // from the parent in the code below.
    const bool needsSceneInit = !oldParentNode
            || (oldParentNode && m_parentId != oldParentNode->id());

    // If we had a parent, we let him know that we are about to change
    // parent
    if (oldParentNode && m_hasBackendNode) {
        QNodePrivate::get(oldParentNode)->_q_removeChild(q);

        // If we have an old parent but the new parent is null
        // the backend node needs to be destroyed
        if (!parent)
            notifyDestructionChangesAndRemoveFromScene();
    }

    // Flag that we need to notify any new parent
    m_notifiedParent = false;

    // Basically QObject::setParent but for QObjectPrivate
    QObjectPrivate::setParent_helper(parent);
    QNode *newParentNode = q->parentNode();

    if (newParentNode) {
        // If we had no parent but are about to set one,
        // we need to send a QNodeCreatedChange
        if (needsSceneInit) {
            QNodePrivate *newParentPrivate = QNodePrivate::get(newParentNode);

            // Set the scene helper / arbiter
            if (newParentPrivate->m_scene) {
                QNodeVisitor visitor;
                visitor.traverse(q, newParentNode->d_func(), &QNodePrivate::setSceneHelper);
            }

            // We want to make sure that subTreeRoot is always created before
            // child.
            // Given a case such as below
            // QEntity *subTreeRoot = new QEntity(someGlobalExisitingRoot)
            // QEntity *child = new QEntity();
            // child->setParent(subTreeRoot)
            // We need to take into account that subTreeRoot needs to be
            // created in the backend before the child.
            // Therefore we only call notifyCreationChanges if the parent
            // hasn't been created yet as we know that when the parent will be
            // fully created, it will also send the changes for all of its
            // children

            if (QNodePrivate::get(newParentNode)->m_hasBackendNode)
                notifyCreationChange();
        }

        // If we have a valid new parent, we let him know that we are its child
        QNodePrivate::get(newParentNode)->_q_addChild(q);
    }
}
Example #5
0
void QCollisionAspect::setRootEntity(QEntity *rootObject)
{
    QNodeVisitor visitor;
    visitor.traverse(rootObject, this, &QCollisionAspect::visitNode);
}