phaser icon indicating copy to clipboard operation
phaser copied to clipboard

Input.alwaysEnabled does not work when a interactive game object is below it

Open EmilSV opened this issue 3 years ago • 4 comments

Version

  • Phaser Version: 3.52 only

Description

interactive object that are invisible and has a interactive object behind it, do not receive input events even if it has "input.alwaysEnabled = true"

Example Test Code

var config = {
    type: Phaser.WEBGL,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: {
        create: create
    }
};

var game = new Phaser.Game(config);

function create() 
{
    var invisibleRect = this.add.rectangle(400, 300, 256, 256, 0x00ff00);
    var rect = this.add.rectangle(400, 300, 256, 256, 0x0000ff).setDepth(-1);
    var text = this.add.text(128, 128, "0").setFontSize(28);
    var count = 0;

    invisibleRect.setInteractive();
    invisibleRect.input.alwaysEnabled = true;
    invisibleRect.on('pointerdown', function () {
        count++;
        text.text = count.toString();
    });

    rect.setInteractive();

    invisibleRect.alpha = 0;
}

Additional Information

Did some testing a i begin to get the bug after the commit "616566c - Renamed sortGameObjects to sortDropZones and then repurposed the old method for the new render list sorting technique."

EmilSV avatar Jan 15 '21 18:01 EmilSV

Thank you for submitting this issue. We have fixed this and the fix has been pushed to the master branch. It will be part of the next release. If you get time to build and test it for yourself we would appreciate that.

photonstorm avatar Dec 01 '21 17:12 photonstorm

I test it in my project it did not fix the issue. The problem is that invisible game objects with "input.alwaysEnabled = true" it is always put behind visible game object when it come to input even when the depth of the invisible game object is higher.

for the project i am working on we did fixed it by using a sort function like this in inputPlugin:

    sortGameObjects: function (gameObjects, pointer)
    {
        if (gameObjects.length < 2 || !pointer.camera)
        {
            return gameObjects;
        }

        var list = pointer.camera.renderList;

        var _this = this;

        return gameObjects.sort(function (childA, childB)
        {
            var ia = list.indexOf(childA);
            var ib = list.indexOf(childB);

            if (ia === -1 || ib === -1)
            {
                if ((childA.input && childA.input.alwaysEnabled) ||
                    (childB.input && childB.input.alwaysEnabled))
                {
                    return _this.sortDropZoneHandler(childA, childB);
                }
            }

            return ib - ia;
        });
    }

But i am not confident that it is good fix for the problem but it works in our case

EmilSV avatar Dec 07 '21 12:12 EmilSV

Using your test passes with a fresh build of Beta 4: http://labs.phaser.io/view.html?src=src%5Cbugs%5C5507%20always%20enabled.js&v=dev

photonstorm avatar Dec 07 '21 16:12 photonstorm

My test is not great it only has one object that is below the invisible one and because both the visible and invisible is at sorted as if they have a index of 0 in the renderList. It appears that work, but if you add one more object it fails.

var config = {
    type: Phaser.AUTO,
    parent: 'phaser-example',
    width: 800,
    height: 600,
    scene: {
        create: create
    }
};

var game = new Phaser.Game(config);

function create()
{
    var invisibleRect = this.add.rectangle(400, 300, 300, 300, 0x00ff00);
    var rect = this.add.rectangle(400, 300, 256, 256, 0x0000ff).setAlpha(0.5);
    var rect2 = this.add.rectangle(350, 300, 256, 256, 0xff0000).setAlpha(0.5);
    var text = this.add.text(128, 128, "0").setFontSize(28);
    var count = 0;

    invisibleRect.name = 'invis';
    invisibleRect.setInteractive();
    invisibleRect.input.alwaysEnabled = true;

    invisibleRect.on('pointerdown', function () {
        count++;
        text.text = count.toString();
    });

    rect.name = 'rect';
    rect.setInteractive();
    
    rect2.name = "rect2"
    rect2.setInteractive();

    invisibleRect.alpha = 0;
    //invisibleRect.alpha = 0.3;

    invisibleRect.setDepth(1);
    rect.setDepth(-2);
    rect2.setDepth(-1);
}

https://user-images.githubusercontent.com/3351370/145205086-a74959c6-ef86-437b-83c6-e356bcbabaad.mp4

EmilSV avatar Dec 08 '21 12:12 EmilSV

Looking at this further, the issue is this line of code within sortGameObjects: var list = pointer.camera.renderList; because the invisible rectangle won't be on this list, so won't get an index. Swapping this to use the Display List instead fixes this issue. Finally!

photonstorm avatar Nov 21 '22 23:11 photonstorm