Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QML Custom Shape Clip
Forum Updated to NodeBB v4.3 + New Features

QML Custom Shape Clip

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
4 Posts 2 Posters 1.5k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • DanimaD Offline
    DanimaD Offline
    Danima
    wrote on last edited by Danima
    #1

    Hi
    I need an Item that clip children's in custom shape like circle.
    I write CircleClip in C++ and create a QSGClipNode inside it. but QSGClipNode don't clip item's that append in qml environment. for example I add a rectangle(brown) to clip node in C++ and clipping work. but when I add another rectangle(green) inside qml clipping not work.
    I need clipping item's in this manner because it use OpenGl stencil method and it's performance needed.
    circle clip.png

    the sceneGraph tree dump is as follows

    RootNode 0x1a973b80d10 "" )
    --TransformNode( 0x1a97459fb20 identity "QQuickItem(QQuickRootItem:)" )
    ----TransformNode( 0x1a9745a1ce0 identity "QQuickItem(QQuickItem:)" )
    ------TransformNode( 0x1a9745a0f60 det= -1 "" )
    --------ClipNode( 0x1a973b67bd0 children= 1 is rect? no ) ""
    ----------GeometryNode( 0x1a9000aea50 strip #V: 4 #I: 0 x1= -235 y1= -160 x2= 236 y2= 160 materialtype= 0x7ffec389a571 ) ""
    ------TransformNode( 0x1a9745a1f20 translate 0 80 0 "QQuickItem(QQuickRectangle:)" )
    --------GeometryNode( 0x1a97120c720 strip #V: 4 #I: 4 x1= 0 y1= 0 x2= 471 y2= 160 materialtype= 0x7ffec389afc0 ) "internalrectangle"

    I uploded project in Github.
    https://github.com/hoss291069/qml-CircleClip.git](https://github.com/hoss291069/qml-CircleClip.git)

    CircleClip.cpp

    CircleClip::CircleClip()
    {
    
        setFlag(ItemHasContents, true);
    
        if(initialized==false)
        {
            double d=2.0f/steps*M_PIF;
            double t=M_PIF_2;
            for(int i=0;i<=steps;++i,t-=d)
            {
                qsgUintCircle[i].set(cosf(t),sinf(t));
            }
            initialized=true;
        }
    
        QObject::connect(this,&QQuickItem::widthChanged,this,&QQuickItem::update);
        QObject::connect(this,&QQuickItem::heightChanged,this,&QQuickItem::update);
    }
    
    
    QSGNode* CircleClip::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
    {
        QSGTransformNode*  rootNode;
        QSGClipNode *      clipNode;
        QSGGeometry*       geometry;
        QSGSimpleRectNode*  rectNode;
    
    
    
        if (!oldNode) {
            rootNode= new QSGTransformNode();
            clipNode= new QSGClipNode();
            rectNode= new QSGSimpleRectNode();
            rectNode->setColor("brown");
            clipNode->setIsRectangular(false);
            geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 1000*3+12);
            clipNode->setGeometry(geometry);
            geometry->setDrawingMode(QSGGeometry::DrawTriangles);
            clipNode->setFlag(QSGNode::OwnsGeometry);
            rootNode->appendChildNode(clipNode);
            clipNode->appendChildNode(rectNode);
    
        } else {
    
            rootNode = static_cast<QSGTransformNode *>(oldNode);
            clipNode = static_cast<QSGClipNode *>(rootNode->firstChild());
            rectNode = static_cast<QSGSimpleRectNode *>(clipNode->firstChild());
            geometry = clipNode->geometry();
        }
    
        QMatrix4x4 n{1,0,0,static_cast<float>(width()/2.0),
                     0,-1,0,static_cast<float>(height()/2.0),
                     0,0,1,0,
                     0,0,0,1
                    };
    
        rootNode->setMatrix(n);
        rootNode->markDirty(QSGNode::DirtyMatrix);
    
        rectNode->setRect(QRect(-width()/2,-height()/2,width(),height()));
        rectNode->markDirty(QSGNode::DirtyGeometry);
    
        QSGGeometry::Point2D* points = geometry->vertexDataAsPoint2D();
    
        int r_px=width()>height() ? height()/2.0 : width()/2.0;
        int k=0;
        for(int i=0;i<250;i++,k+=3)
        {
            points[k+0].set(width()/2.0,height()/2.0);
            points[k+1].set(qsgUintCircle[i].x *r_px  , qsgUintCircle[i].y * r_px);
            points[k+2].set(qsgUintCircle[i+1].x *r_px  , qsgUintCircle[i+1].y * r_px);
        }
    
        for(int i=250;i<500;i++,k+=3)
        {
            points[k+0].set(width()/2.0,-height()/2.0);
            points[k+1].set(qsgUintCircle[i].x *r_px  , qsgUintCircle[i].y * r_px);
            points[k+2].set(qsgUintCircle[i+1].x *r_px  , qsgUintCircle[i+1].y * r_px);
        }
    
        for(int i=500;i<750;i++,k+=3)
        {
            points[k+0].set(-width()/2.0,-height()/2.0);
            points[k+1].set(qsgUintCircle[i].x *r_px  , qsgUintCircle[i].y * r_px);
            points[k+2].set(qsgUintCircle[i+1].x *r_px  , qsgUintCircle[i+1].y * r_px);
        }
    
        for(int i=750;i<1000;i++,k+=3)
        {
            points[k+0].set(-width()/2.0,height()/2.0);
            points[k+1].set(qsgUintCircle[i].x *r_px  , qsgUintCircle[i].y * r_px);
            points[k+2].set(qsgUintCircle[i+1].x *r_px  , qsgUintCircle[i+1].y * r_px);
        }
    
        points[k++].set(width()/2.0,height()/2.0);
        points[k++].set(r_px  ,0);
        points[k++].set(width()/2.0 ,-height()/2.0);
    
        points[k++].set(width()/2.0,-height()/2.0);
        points[k++].set(0  ,-r_px);
        points[k++].set(-width()/2.0 ,-height()/2.0);
    
        points[k++].set(-width()/2.0,height()/2.0);
        points[k++].set(0  ,r_px);
        points[k++].set(width()/2.0 ,height()/2.0);
    
        points[k++].set(-width()/2.0,height()/2.0);
        points[k++].set(-r_px  ,0);
        points[k++].set(-width()/2.0 ,-height()/2.0);
    
        return rootNode;
    }
    
    

    main.qml

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import Test 1.0
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        CircleClip{
            anchors.fill: parent;
    
            Rectangle
            {
                id:greenRect
                width:parent.width
                height: parent.height/2
                anchors.centerIn: parent
                color:"green"
            }
        }
    }
    
    
    1 Reply Last reply
    0
    • MarkkyboyM Offline
      MarkkyboyM Offline
      Markkyboy
      wrote on last edited by
      #2

      I think the problem is because you are nesting your code. Instead, swap CircleClip and Rectangle around and keep inline, don't nest.

      This works;

      import QtQuick 2.12
      import QtQuick.Window 2.12
      import Test 1.0
      
      Window {
          visible: true
          width: 640
          height: 480
          title: qsTr("Clipping")
      
          Rectangle {
              id: greenRect
              width: parent.width
              height: parent.height / 2
              anchors.centerIn: parent
              color: "green"
          }
          CircleClip {
              anchors.fill: parent
          }
      }
      

      IF the problem is not because of nesting code, I'd be happy to hear from someone :)

      Capture.JPG

      Don't just sit there standing around, pick up a shovel and sweep up!

      I live by the sea, not in it.

      1 Reply Last reply
      0
      • DanimaD Offline
        DanimaD Offline
        Danima
        wrote on last edited by
        #3

        It doesn't Clip green rectangle. It just mask that and if my CircleClip doesn't have a brown rectangle the green rectangle Can be seen.
        Basically clipping term used when item's are inside clipper item. and I need children inside CircleClip to be clipped.

        DanimaD 1 Reply Last reply
        0
        • DanimaD Danima

          It doesn't Clip green rectangle. It just mask that and if my CircleClip doesn't have a brown rectangle the green rectangle Can be seen.
          Basically clipping term used when item's are inside clipper item. and I need children inside CircleClip to be clipped.

          DanimaD Offline
          DanimaD Offline
          Danima
          wrote on last edited by Danima
          #4

          @Danima
          basically according to tree dump the problem is that the CircleClip child is not descendant of ClipNode.
          QQuickItem for each item create one TransformNode to map coordinate system. All item's children are descendant of TransformNode.
          I want a way to some thing like replace or embed ClipNode with TransformNode .

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved