Help! Mouseenter / Mouseleave on elements isn’t firing correctly. How can I resolve this?
I have some ui buttons with mouseenter and mouseleave events. These work as expected, except that the mouse position is incorrect when these events are fired, due to my fixing of the aspect ratio of the application and centering it on screen.
When I run the application, the ui elements appear where I expect them to. However, the mouseenter and mouseleave events are NOT fired when the mouse crosses over the boundary of the elements. Rather, the events are fired at some offset to these, related to how I’m offsetting and resizing the application.
Here is a video demonstrating the issue: https://youtu.be/vOfC92hd87c
Here is my resize code.
Note - I tried updating to the latest Playcanvas build from their github. Issue was not resolved, and it broke pc.extends for my shader logic so I reverted.
Note - I have also tried pc.FILLMODE_KEEP_ASPECT, pc.FILLMODE_NONE, pc.RESOLUTION_FIXED, pc.RESOLUTION_AUTO for the resolution and fillmode options, as well as pc.SCALEMODE_BLEND and pc.SCALEMODE_FIXED for the UI screen element, and they all have the same result (the element mouseenter and mouseleave events are not firing at the correct location). I’ve also tried manually setting the resolution of my “screen” component to the correct value. Nothing works!
relevant parts of my “GUI / element” code:
const gui = new pc.Entity();
InGameGui.screen = gui;
gui.addComponent("screen", {
referenceResolution: new pc.Vec2(Constants.Resolution.width,Constants.Resolution.height),
scaleBlend: 1.0,
scaleMode: pc.SCALEMODE_BLEND,
screenSpace: true,
});
Camera.sky.entity.addChild(gui);
const child = new pc.Entity("childe");
child.addComponent("element", {
anchor: [0.5, 0.5, 0.5, 0.5],
pivot: [0.5, 0.5],
type: 'image',
textureAsset: assets.quad,
opacity:0.4,
color:new pc.Color(0,1,0.5),
width:100,
height:100,
useInput:true,
});
child.addComponent("layoutchild", {
excludeFromLayout: false,
});
child.element.on('mouseenter',function(){ child.element.color = new pc.Color(0,1,0); })
child.element.on('mouseleave',function(){ child.element.color = new pc.Color(0,1,0.5); })
resize code:
function ResizeCanvas2(){
// This is awkwward. Playcanvas doesnt seem to respect resized canvas in x-direciton and won't properly detect mousedown events on elements if the canvas is not as wide as the screen, no matter what fillmode, resolution, canvas size, etc that you set to. So I'm going to manually detect where the cursor is vs where elements are, and check that way.
// SO, we are forced to determine hovered ui elements by comparing element.screenCorners to mousePosition including our manual offset to center the screen. dislike loll
// console.log("w,h:"+window.innerWidth+","+window.innerHeight);
const aspectRatio = {w : 8, h:5 };
const winWidth = $(window).innerWidth();
const winHeight = $(window).innerHeight();
var w = winWidth;
var h = winHeight;
var offset = canvasOffset;
if (winWidth / winHeight > aspectRatio.w / aspectRatio.h){
// Calculate and set new resolution at aspect ratio constraint.
let resX = parseInt(winHeight * aspectRatio.w/aspectRatio.h);
let resY = parseInt(winHeight);
// console.log("xy1:"+resX+", "+resY+", winh:"+winHeight);
pc.app.setCanvasFillMode(pc.FILLMODE_NONE,resX,resY);
pc.app.setCanvasResolution(pc.RESOLUTION_FIXED,resX,resY);
// Bars on left and right. Image is less wide than total page width.
w = winHeight * aspectRatio.w/aspectRatio.h;
offset.left = (winWidth - w)/2;
} else {
// Calculate and set new resolution at aspect ratio constraint.
let resX = parseInt(winWidth);
let resY = parseInt(winWidth * aspectRatio.h/aspectRatio.w);
pc.app.setCanvasFillMode(pc.FILLMODE_NONE,resX,resY);
pc.app.setCanvasResolution(pc.RESOLUTION_FIXED,resX,resY);
// console.log("xy2:"+resX+", "+resY);
// Bars on top and bottom. Image is as wide as the total page width.
h = winWidth * aspectRatio.h/aspectRatio.w;
offset.top = (winHeight-h)/2;
}
pc.app.resizeCanvas();
$('#application').css('margin-left',offset.left).css('margin-top',offset.top);
}