Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

Forums

OverviewFelgo 3 Support (Qt 5) › Pixel Perfect Mouse Click

Viewing 10 posts - 1 through 10 (of 10 total)
  • Author
    Posts
  • #15855

    Joachim

    Hi,

    I want to build a kind of hidden object game for my kids.

    Now I searched the forums and documentation and cannot find any hint on how to implement pixel perfect mouse click handling on entities.
    I have some png sprites with transparent background and would like to retrieve only a “pressed” event if the mouse is actually over a non transparent part.

    Are there any ways to achieve that? E.g testing for transparent pixel?

    #15857

    Alex
    Felgo Team
    #15860

    Joachim

    Thanks. It somehow worked for me but only with a “workaround” I do not understand…

    See the below code that handles the click in the canvas with the image.

     

          MouseArea {
                anchors.fill: parent
                propagateComposedEvents: true
    
                onClicked: {
                    var ctx = parent.getContext("2d")
    
                    // get the pixelData
                    var pixelData = ctx.getImageData(mouse.x * 2, mouse.y * 2, 1, 1).data
    
                    console.log("Clicked on entity: " + parent.parent.entityId
                                + " mX: " + mouse.x + " mY: " + mouse.y)
    
                    if ((pixelData[0] === 0) && (pixelData[1] === 0)
                            && (pixelData[2] === 0) && (pixelData[3] === 0)) {
                        // If transparency on the pixel , array = [0,0,0,0] detected then do nothing and dont accept the mouse event
                        mouse.accepted = false
                    } else {
                        //otherwise react on the click and remove entity for now
                        removeEntity()
                    }
                }
            }

     

     

    The only way to get the correct pixel values in red,green,blue,alpha is to use

    mouse.x * 2, mouse.y * 2

    in

    ctx.getImageData(

    Any idea or hint why do I need to double the mouse.x and mouse.y coordinates?

     

    #15863

    Alex
    Felgo Team

    Hi Joachim,

    this is related to the scene scaling mechanism of Felgo. If you do not know what this is, please quickly check out this tutorial: https://felgo.com/doc/vplay-different-screen-sizes/

    Basically your logical scene is scaled up to fit in the device screen resolution, and images are selected in different qualities accordingly to look crisp. So in your case the Scene is e.g. 480×320, while your GameWindow (which represents the screen) is 960×640, which equals a scale factor of 2. You can access this scale factor via a property of your Scene, the xScaleForScene (with the default scaling, it has the same value as the xScaleForScene, so you can use both). This is the multiplier you should use so it works on every resolution.

    The canvas internally is not aware of the scaling, that’s why you need to care about this manually in your case.

    Cheers,
    Alex

    #15867

    Joachim

    Hi,

    thanks for the quick reply. I thought I understood the handling of different screen sizes but now I am even more confused 😉

    I checked my code and debugged a little bit… and now I have some more questions

    1. Whats the best way to get the current scene in a mousearea event handler to read the value for xScaleForScene?
    2. I used an ugly parent.parent.parent construct to get the scene and saw the values for xScaleForScene and yScaleForScene are both 1 as I expected because my Scene and my GameWindow used the same dimensions. But I saw uiScale at value 2 that I expected to (default) 1 as documented maybe that would be the correct value?
    3. Why is uiScale eq 2?
    4. Is there a reason why the canvas is not aware of the scaling?

    One idea I had could be my use of MacOS with its retina scaling but maybe I am complety wrong here…

    #15873

    Joachim

    Mhh I just made a quick test with the same code in Windows – no corection (*2) needed here. uiScale is 2 and xScaleForScene and yScaleForScene are both 1

    :S

     

    #15876

    Günther
    Felgo Team

    Hi Joachim!

    To target the scene without moving upwards in your QML hierarchy using parent.parent… I suggest to give your scene an ID:

    Scene {
      id: myScene
      // ...
    }

    You can then access e.g. myScene.xScaleForScene from any item within your scene.

    In case you want to use your Canvas Item within multiple different scenes that have different identifiers, you can also add a property which you can set to the correct value when using your Canvas:

    Scene {
      id: scene
      MyCanvasItem {
        scaleFactor: scene.xScaleForScene
      }
    
      /*
      MyCanvasItem must then define a property:
      property real scaleFactor
      which you can then use within the Canvas Item
      */
    }

    The uiScale does not affect the Scene scaling and only applies for items that use the scenes dp(…) or sp(…) functions to specify density-independent UI elements (e.g. items with a fixed width of dp(200) have the same size regardless of the device or actual scene scaling)). Changing the uiScale then allows making these elements bigger or smaller in your application. A uiScale of 2 is only the default value when testing the application on desktop. You can ignore this setting if you do not use the dp(…) or sp(…) functions in your project.

    Based on your recent test on Windows I also assume that the issue is not related to scene scaling or the uiScale setting – maybe you’re right about the retina screen? You can also run a simple test with a plain Qt Quick Application (no Felgo) to see how the Qt Canvas behaves on different platforms / screens. If the issue persists, then this is definitely not Felgo related but a general Qt issue.

    Best,
    Günther

     

     

    #15877

    Joachim

    Hi,

    Thanks for the answer regarding scene and uiScale.

    I just followed the path with the retina idea and found the following:

    Regarding canvas and the backing store in retina context

    https://www.html5rocks.com/en/tutorials/canvas/hidpi/

    Documentation in QML doc

    http://doc.qt.io/qt-5/qml-qtquick-window-screen.html#devicePixelRatio-attached-prop

     

    Screen.devicePixelRatio

    “… Common values are 1.0 on normal displays and 2.0 on Apple “retina” displays…”

     

    So adding

     

    import QtQuick.Window 2.0

     

    and

     var pixelData = ctx.getImageData(mouse.x * Screen.devicePixelRatio, mouse.y*Screen.devicePixelRatio , 1, 1).data
    

     

    leads to a solution under macOs Sierra. Yay! 😉

    I will double check this with my Windows System…

    Maybe you add a hint somewhere in the doc or add an example so other user do not walk into this trap.

    Thanks again

     

    #15878

    Joachim

    Quick addition:

    Code works as expected in non Retina MacOS environment (devicePixelRatio returned is 1)

    EDIT:

    Also works in Windows with devicePixelRatio 1

    #15880

    Günther
    Felgo Team

    Hi Joachim,

    Thanks for sharing your solution!

    Happy to hear you got it working 😉

    Cheers,
    Günther

Viewing 10 posts - 1 through 10 (of 10 total)

RSS feed for this thread

You must be logged in to reply to this topic.

Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded