Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-42339

x and y offset on tiled images

    XMLWordPrintable

Details

    • Suggestion
    • Resolution: Unresolved
    • P4: Low
    • None
    • None
    • None
    • Tested this on OS X Mavericks with Qt 5.3.0

    • All

    Description

      I run into a problem when making a game, I want to do a parallax background but when I set an image with the Tile property I couldn't move the image while maintaining the Image object on the same position.

      So I hacked the source code of the qml image object to have two new properties: xTileOffset and yTileOffset.

      512kb video showing red balls being animated moving to the side:
      http://real.purpleorangegames.com/wp-content/uploads/2014/05/TestingTileOffset2.mp4
      Vimeo version of the video:
      https://vimeo.com/96127913
      (It is still being processed at the time I published this post)

      And the code is quite simple:

       Image
       {
        anchors.fill: parent
        source: "Images/Background/AnimCircle/10.png"
        fillMode: Image.Tile
        SequentialAnimation on xTileOffset
        {
         running: true
         loops: Animation.Infinite
         NumberAnimation { to: 101; duration: 500 }
        }
       }
      

      The image covers the parent, the entire window.
      It has 101×101 pixels, it's a red ball on a transparent background.
      So when I animate the xTileOffset it looks like I'm moving the Image object to the side but the Image actually remains at the same place.

      I modified the following files in QtDeclarative/src/quick/items/ :
      qquickimage_p_p.h
      qquickimage_p.h
      qquickimage.cpp

      Adding to qquickimage_p_p.h the variables on the class QQuickImagePrivate:
      qreal xTileOffset;
      qreal yTileOffset;
      Then I added to qquickimage_p.h the following to the class QQuickImage:

          Q_PROPERTY(qreal xTileOffset READ xTileOffset WRITE setXTileOffset NOTIFY xTileOffsetChanged)
          Q_PROPERTY(qreal yTileOffset READ yTileOffset WRITE setYTileOffset NOTIFY yTileOffsetChanged)
       
      public:
          qreal xTileOffset() const;
          qreal yTileOffset() const;
          void setXTileOffset(qreal value);
          void setYTileOffset(qreal value);
       
      Q_SIGNALS:
          void xTileOffsetChanged();
          void yTileOffsetChanged();
      

      And finally I added to qquickimage.cpp:

      qreal QQuickImage::xTileOffset() const
      {
          Q_D(const QQuickImage);
          return d->xTileOffset;
      }
       
      qreal QQuickImage::yTileOffset() const
      {
          Q_D(const QQuickImage);
          return d->yTileOffset;
      }
       
      void QQuickImage::setXTileOffset(qreal value)
      {
          Q_D(QQuickImage);
          if (d->xTileOffset == value)
              return;
       
          d->xTileOffset = value;
          update();
          updatePaintedGeometry();
          emit xTileOffsetChanged();
      }
       
      void QQuickImage::setYTileOffset(qreal value)
      {
          Q_D(QQuickImage);
          if (d->yTileOffset == value)
              return;
       
          d->yTileOffset = value;
          update();
          updatePaintedGeometry();
          emit yTileOffsetChanged();
      }
      

      And the most important part, inside the function
      QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)

      you can see the variables that I created (xTileOffset and yTileOffset):

          case Tile:
              targetRect = QRectF(0, 0, width(), height());
              sourceRect = QRectF(-xOffset+xTileOffset(), -yOffset+yTileOffset(), width(), height());
              hWrap = QSGTexture::Repeat;
              vWrap = QSGTexture::Repeat;
              break;
       
          case TileHorizontally:
              targetRect = QRectF(0, 0, width(), height());
              sourceRect = QRectF(-xOffset+xTileOffset(), 0, width(), d->pix.height());
              hWrap = QSGTexture::Repeat;
              break;
       
          case TileVertically:
              targetRect = QRectF(0, 0, width(), height());
              sourceRect = QRectF(0, -yOffset+yTileOffset(), d->pix.width(), height());
              vWrap = QSGTexture::Repeat;
              break;
      

      And that's it.
      Other examples that I use this properties:
      (Two scanlines and one is animated)

       Image
       {
        id: scanLines
        anchors.fill: parent
        fillMode: Image.Tile
        source: "Images/Background/lines2.png"
        opacity: 0.3
        asynchronous: true
        SequentialAnimation
        {
         running: true
         loops: Animation.Infinite
         NumberAnimation { target: scanLines; properties: "yTileOffset"; from: 0; to: 1; duration: 500 }
         NumberAnimation { target: scanLines; properties: "yTileOffset"; from: 1; to: -1; duration: 500 }
         NumberAnimation { target: scanLines; properties: "yTileOffset"; from: -1; to: 0; duration: 500 }
        }
        Image
        {
         anchors.fill: parent
         fillMode: Image.Tile
         source: "Images/Background/lines.png"
         opacity: 0.2
         asynchronous: true
        }
       }
      
      (parallax background)
       Image
       {
        property double vel: 0.8
        width: parent.width
        height: parent.height
        anchors.centerIn: parent
        xTileOffset: parseInt(flick.contentX*vel)
        yTileOffset: parseInt(flick.contentY*vel)
        source: "Images/Other/SpaceTileBigger.png"
        fillMode: Image.Tile
        opacity: level1Opacity
        asynchronous: true
       }
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            Unassigned Unassigned
            tiagocc0 Tiago de Castro Carvalho
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes