Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FlxMouseEventManager: check objects for camera overlap #1964

Merged
merged 4 commits into from
Dec 20, 2016

Conversation

bendmorris
Copy link
Contributor

The problem: when using FlxCameras that don't cover the whole screen, mouse events can be generated by FlxMouseEventManager when the mouse isn't within the camera's visible area.

Example: this scrolling button menu has its own FlxCamera. The top button is highlighted by an onMouseOver callback, even though the overlapping part is above the camera's visible area:

screen shot 2016-09-28 at 8 32 09 am

With this change, FlxMouseEventManager first checks that the screen coordinates are within the camera's bounds before checking if the object overlaps the mouse position.

screen shot 2016-09-28 at 8 34 15 am

@Gama11
Copy link
Member

Gama11 commented Sep 28, 2016

Would be nice to have a unit test for this.

@Gama11 Gama11 added the Bug label Sep 28, 2016
@bendmorris
Copy link
Contributor Author

Testing this will be hacky since it's a singleton. I would suggest adding tests once this is merged: #1961 which makes FlxMouseEventManager modular and easier to write self-contained tests for.

@Gama11
Copy link
Member

Gama11 commented Sep 29, 2016

I don't think that really impacts testing too much. Besides, I don't have any plans to merge that anytime soon, it just breaks too much (essentially all usages of FlxMouseEventManager).

@bendmorris
Copy link
Contributor Author

It's a breaking change, so it wouldn't go in a minor release, I get that. (To be clear you just have to add globalManager to any use of FlxMouseEventManager to get exactly the same behavior, it's not a difficult migration.) There are other breaking changes such as #1940 in the pipeline. What's the plan for landing them?

If it's not clear that it will ever be merged, I'm going to continue using my modular version, so I'm probably not going to write new tests for the singleton version, and this fix will become "take it or leave it."

@Gama11
Copy link
Member

Gama11 commented Sep 29, 2016

Not going in a minor release means that it would have to wait until 5.0.0 - there are no concrete plans for that yet.

So far we've avoided breaking changes since 4.0.0, except for bugfixes where it was inevitable (what's broken there is just relying on broken behavior) and #1934. That PR only breaks usage of a field that is hardly used by anyone, and it didn't even break any of the demos - whereas this PR would break all usages of FlxMouseEventManager.

I'll have to check in more detail what exactly #1940 breaks - so far it's scheduled for a minor release (4.3.0). Either way it's a bit of a special case.

*/
public inline function containsPoint(point:FlxPoint, width:Float = 0, height:Float = 0):Bool
{
return (point.x + width >= 0) && (point.x < this.width) && (point.y + height >= 0) && (point.y < this.height);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like you also changed this logic to be inclusive? (>= 0 instead of just > 0). This leads to unexpected behavior in FlxObject#isOnScreen():

var object = new FlxObject(0, 0, 1, 1);
add(object);
trace(object.isOnScreen()); // true
object.x = -1;
trace(object.isOnScreen()); // should be false, but true with >= 0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, I'll take that out.

@Gama11
Copy link
Member

Gama11 commented Sep 30, 2016

I can still reproduce the issue you describe if I'm on your branch... Am I missing something?

package;

import flixel.input.mouse.FlxMouseEventManager;
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.FlxState;
import flixel.util.FlxColor;

class PlayState extends FlxState{
    override public function create():Void {
        var sprite = new FlxSprite(0, 0);
        sprite.makeGraphic(20, 20);
        add(sprite);
        sprite.screenCenter();

        FlxG.camera.zoom = 4;
        FlxG.camera.y = FlxG.height / 2;
        FlxG.camera.scroll.y = 60;

        FlxMouseEventManager.add(sprite, null, null,
            function(_) sprite.color = FlxColor.RED,
            function(_) sprite.color = FlxColor.WHITE);
    }
}

@bendmorris
Copy link
Contributor Author

The difference is zoom - if you remove zoom from your demo and change FlxG.camera.scroll.y to FlxG.height/2, it works. It looks like getScreenPosition doesn't incorporate camera scale. I'm not sure what the proper fix for that would be.

@Gama11 Gama11 changed the title FlxMouseEventManager: check camera for overlap before checking object. FlxMouseEventManager: check objects for camera overlap Oct 9, 2016
_point = touch.getWorldPosition(camera, _point);

if (checkOverlapWithPoint(Register, _point, camera))
_point = touch.getScreenPosition(camera, _point);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this line should be changes as well to
_point = touch.getPositionInCameraView(camera, _point);

_point = FlxG.mouse.getWorldPosition(camera, _point);

if (checkOverlapWithPoint(Register, _point, camera))
_point = FlxG.mouse.getScreenPosition(camera, _point);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i've found that if we change this _point caclulation code _point = FlxG.mouse.getScreenPosition(camera, _point); to something like this:

public function getPositionInCameraView(?Camera:FlxCamera, ?point:FlxPoint):FlxPoint
    {
        if (Camera == null)
            Camera = FlxG.camera;

        if (point == null)
            point = FlxPoint.get();

        point.x = (_globalScreenX - Camera.x) / Camera.zoom;
        point.y = (_globalScreenY - Camera.y) / Camera.zoom;

        return point;
    }

then checks working properly.

This new method calculates position of a point relative to camera view rectangle

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You named the function wrong! The function in FlxPointer is not the same name as in FlxMEM.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MSGhero already fixed this, sorry

@bendmorris
Copy link
Contributor Author

Thanks @Beeblerox. You should have commit access to my fork, so feel free to just push your change there, otherwise I'll add them when I have a chance.

@Gama11 Gama11 added this to the 4.3.0 milestone Oct 12, 2016
@Beeblerox Beeblerox merged commit 948b03f into HaxeFlixel:dev Dec 20, 2016
Aurel300 pushed a commit to larsiusprime/haxeflixel that referenced this pull request Apr 18, 2018
* FlxMouseEventManager: check camera for overlap before checking object.

* Update FlxMouseEventManager.hx

* Update FlxPointer.hx

* Update FlxPointer.hx
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants