-1

How to use QSGClipNode with a custom geometry?
This is a sample:

enter image description here

S.M.Mousavi
  • 5,013
  • 7
  • 44
  • 59
  • What exactly the problem with using `setGeometry(QSGGeometry *geometry)`? – Velkan Mar 06 '17 at 08:57
  • I don't know how to use `QSGClipNode` and official documentation is poor. So this question will be a reference for anybody whom wants to know how to do clipping in the scenegraph within QQuickItem in a CORRECT WAY. – S.M.Mousavi Mar 06 '17 at 09:29
  • It's your question that is poor for StackOverflow. What have you tried? Any code to reproduce the problem? What was the error or the desired effect? Here is an example with `QSGGeometryNode`: http://doc.qt.io/qt-5/qtquick-scenegraph-customgeometry-example.html – Velkan Mar 06 '17 at 10:03
  • Do you tried to use `QSGClipNode`?! It is different from `QSGGeometryNode`. My question is very simple and clear... "how to use QSGClipNode?" Have you any sample code which uses `QSGClipNode`? – S.M.Mousavi Mar 06 '17 at 10:12

1 Answers1

1

QSGClipNode

The QSGClipNode uses its geometry to clip rendering of its children nodes.

So to use it, you first have to create the geometry (set of vertices/triangles) representing your mask, and set it with the setGeometry method. Resources are scarce yes, here is a few examples using QSGGeometry, that you need to draw your "heart" shape:

Then use the appendChildNode method to add the children that you want to clip in your QSGClipNode. In your case, QSGImageNode is probably the way to go, to show your image clipped.

Other solution: OpacityMask

Another solution, available without digging into c++ scene graph classes, is to use an OpacityMask from QtQuick.GraphicalEffect. It also applies to a QtQuickItem you would have created in C++.

The example in Qt documentation is easy to use, just don't forget to set the visible property of both the Mask and the Source to false, the OpacityMask element itself will display the source cropped/masked.

Here is a way to clip "children" with it (NB: untested at that time):

clipperitem.qml

import QtQuick 2.5
import QtGraphicalEffects 1.0

Item {
    width: 300
    height: 300

    // Item-based children will be mapped to this property
    default property alias clippedContent: clippedItem.children

    // Optional mask property to set it from outside
    property alias mask: opacityMask.mask

    Item {
        id: clippedItem
        anchors.fill: parent
        visible: false
    }

    Item {
        id: defaultMask
        // Your default mask
        visible: false
    }

    OpacityMask {
        id: opacityMask
        anchors.fill: clippedItem
        source: clippedItem
        mask: defaultMask
    }
}

main.qml

ClipperItem {
    // Content here will be clipped. Non item-based elements will have
    // to be explicitly assigned to `ressources` property (i.e. Timer, etc.)
    Rectangle {
        //...
    }
    Image {
        //...
    }
}
Adrien Leravat
  • 2,731
  • 18
  • 32
  • OK, I test it and it clips its child node. Is there any way to clip child QQuickItems? Assume in QML `MyClipItem { width: 45; height: 45; Rectangle { id: rec; width: 50; height: 50; color: "red"; radius: 20 } }` Is it possible to clip `rec` using `MyClipItem`? – S.M.Mousavi Mar 09 '17 at 09:01
  • Good, I would assume it works directly as in your case, your Rectangle is reparented to `MyClipItem`. Have you tried it alredy ? – Adrien Leravat Mar 09 '17 at 09:38
  • I tested it and it works perfect for `QSGNodes` as children but in earlier comment, my Rectangle named `rec` is not clipped. In other words QSGClipNode not clips QQuickItems children such as `rec`. – S.M.Mousavi Mar 09 '17 at 14:11
  • Please try with MyClipItem { clip: true; /*...*/ }, this should do the trick ! – Adrien Leravat Mar 09 '17 at 15:33
  • Ok right, that's actually normal. I edited my answer to include the OpacityMask, which might be helping to you, even though in that case you don't need a `GSGClipNode` anymore. It's however completely possible to use a QSGGeometry in a QQuickItem as the mask – Adrien Leravat Mar 10 '17 at 19:54
  • OK thanks, first section of your answer is the actual answer for my question. Also your alternate solution for clipping using GLSL works perfectly. After testing your first approach I found out that It doesn't clips QQuickItem children. So I'm interested to find a way to clipping children QQuickItems as normal rectangular clipping through C++ but with a custom shape. So I can use it in QML as an Item named: `ClipperItem` – S.M.Mousavi Mar 11 '17 at 06:08
  • I included an example of how this could be achieved using `OpacityMask` – Adrien Leravat Mar 11 '17 at 09:25
  • Thank you @Adrien – S.M.Mousavi Mar 11 '17 at 09:28