pixijs / layers

Separate the z-hierarchy of your scene tree from its canonical structure.
https://pixijs.io/layers/docs/
MIT License
224 stars 57 forks source link

Container mask with children layers breaking interaction events #62

Open jkar32 opened 4 years ago

jkar32 commented 4 years ago

I ran into the situation where a masked parent container with children containers containing multiple layers was sending pointer events to children outside of one of the masked parents.

E.g. image

The application is split into multiple screens, in this case Container 2 and Container 3 are sitting next to each other. These containers have masks so that there children (pixi-viewports) can be used as seperate sections. (imaging multiple lucidchart apps running next to each other on the same canvas).

image

The mask works visually but items on the Container 3 get pointer events before items on Container 2 meaning that Container 2 becomes un-clickable.

I had a bit of a dig and I think I found the culprit but as i am not an expert in pixi.js I am not sure about the repercussions, if this can provide some optimisations or even if this is a bug or not. I have not seen any side effects yet.

https://github.com/pixijs/pixi-layers/blob/a102b5dd13c4c1a52794e512d2ec0eb2a873d0c6/src/LayersTreeSearch.ts#L33

if (displayObject._activeParentLayer) {
    outOfMask = outOfMask || false; // CHANGE
}

// it has a mask! Then lets hit test that before continuing..
const mask: PIXI.Graphics = (displayObject as any)._mask;
if (hitTestOrder < Infinity && mask) {
    if (!mask.containsPoint(point)) {
        outOfMask = outOfMask || true; // CHANGE
    }
}

// it has a filterArea! Same as mask but easier, its a rectangle
if (hitTestOrder < Infinity && displayObject.filterArea) {
    if (!displayObject.filterArea.contains(point.x, point.y)) {
        outOfMask = outOfMask || true; // CHANGE
    }
}

Hope that all makes sense, Julian

ivanpopelyshev commented 4 years ago

I had a bit of a dig and I think I found the culprit but as i am not an expert in pixi.js I am not sure about the repercussions

Nobody does, this thing is hacky. That's why I moved TreeSearch into separate class, so people can experiment by copying LayersTreeSearch and using their own variant.

renderer.plugins.interaction = new MyTreeSearch();

Yes, this code due to be rewritten for several months already, because, honestly, I can just use basic pixi interaction code and add extra cycle for _sortedChildren there.

Regarding your changes: Only first line is actually doing something: you basically removed it. Other two changes do nothing.

I'll consult you when I change that thing, and you'll test it in your app, ok? For now , just using your own interaction algo is completely fine.

jkar32 commented 4 years ago

Ahh yes, dumb of me not to see the other 2 lines do nothing.

Yeah I have been using my own search tree but thought i should post it so other people don’t get stuck.

Happy to test whenever.

Thanks mate!