Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - TheMaskedFox

Pages: [1]
Feature requests / Relative Mouse Movement (Mouse Capture)
« on: October 10, 2012, 03:41:22 am »
This proposal stems from an issue raised on the French forum.


For first-person games with mouse control, developers need relative mouse movement, as opposed to absolute coordinates.  SFML needs either a window style or a window method that locks the mouse, hides the cursor, and sends sf::Event::MouseMove events containing relative x and y updates.

Windows, X11, and OS X will all accomplish this differently, so this feature could take some time to fully implement.  It's critical for providing mouse support in an FPS though, so it would be well worth the time spent.

To accomplish this on OS X, the mouse cursor has to be hidden, the mouse has to be disconnected from the cursor, and the mouse delta has to be polled by the application for changes.  I've posted a sort of "starter kit" for accomplishing this over on Github (https://github.com/SFML/SFML/issues/290#issuecomment-9279071).

It's been so long since I did any WinAPI or X11 development that I don't have immediate suggestions for how to accomplish mouse locking on those platforms.  Relative mouse movement is a feature common to many games, but its implementation is platform specific.  It's the kind of input abstraction that belongs in SFML.

Developers would either call something like window.captureMouse(), or it would be passed as an option on window creation with a style like sf::Style::CaptureMouse.  In either case, they'd receive a window that has essentially "captured" the mouse, locking the cursor down and hiding it so that all mouse movements are reported as some distance from zero.  Anytime the mouse stops moving, it automatically returns to zero, and any further movement is again reported as some distance from zero.

As an example, on the X axis a reading of -5 would mean tell the game that the user moved the mouse slightly to the left.  Another reading of -35 would mean the user moved the mouse to the left faster.  A subsequent reading of 100 would indicate that the user has snapped the mouse quickly to the right.  This is a rough example, but illustrates how relative mouse movements are helpful.

I'm not sure if this is due to changes between one version of OS X and another, or if this is just broken across all versions.  I'm on Lion.

If I call position, and then use its returned point as input to setWindowPositionToX:Y:, the window moves.  That shouldn't happen. :)

Take a look at the following rewrites, which solve the problem for me.  I hope, but don't have an easy way to test, that this rewrite corrects the behavior across all of SFML's supported versions of OS X.

    NSRect frame = m_window.frame;
    NSPoint pos = frame.origin;
    // Flip for SFML window coordinate system.
    pos.y += frame.size.height;
    pos.y = m_window.screen.frame.size.height - pos.y;

    return pos;

-(void)setWindowPositionToX:(unsigned int)x Y:(unsigned int)y
    NSPoint point = NSMakePoint((int)x, (int)y);
    NSScreen *screen = m_window.screen;

    // Flip for SFML window coordinate system.
    point.y = m_window.screen.frame.size.height - point.y;

    // Place the window.
    [m_window setFrameTopLeftPoint:point];
    if (screen != [m_window screen]) {
        // Oops.  Coordinates were for a different screen.  Do-over.
        [self setWindowPositionToX:x Y:y];

The key differences:

position should be using the window's frame, not the OpenGL view's frame (unless there's some reasoning for using the OpenGL view that I'm missing.)

position also must account for the window's size when flipping the y coordinate.

setWindowPositionToX:Y: should be taking ints, not unsigned ints.  It is legitimate for a window to have a negative X or Y, especially in the case of multiple displays (which my changes appear to support without issue).

setWindowPositionToX:Y: also needs to recognize that the coordinates may not be for the main display, and must use the proper display height for adjustment.  There's probably a better way to handle that case than what I did, but what I did is working.  My lazy implementation just checks to see if the repositioned window ended up on a different screen, and if so, recognizes the mistake and repeats the positioning now that m_window.screen points to the screen that the coordinates were supposed to reference.

This came up when I was trying to go from Windowed to Fullscreen to Windowed.  My window would not end up in the right place after exiting Fullscreen.  These changes resolve that.

Upon further reflection, this works fine for side-by-side displays, but is still slightly deficient in a case of vertically or diagonally positioned displays.  I'm doing at bit more exploration to see if I can gracefully resolve vertical positioning despite dealing with a coordinate system translation in the process.

I stand corrected.  (Mostly...)  :)

Turns out this works pretty well for vertically oriented displays too.  It's not perfect.  If the window is placed such that it sits partially in one window's bottom right corner, and partially in another window's top left corner, the positioning will be slightly off if you use the values from a getPosition in a call to setPosition.  However, this solution at least changes the problem from "happens all the time" to "happens in one edge case", and in that edge case the incorrect behavior is now much more minimal.

I think it's as close as I can get without SFML itself being more multi-display aware.  I'm going to push this to my fork of SFML and open a pull request.  If SFML's maintainers don't approve, that's cool.

This whole issue specifically comes up when switching between Window and Fullscreen.  Since SFML dictates that the window has to be recreated each time, there's no internal state on the window itself by which a previous size and location can be remembered.  The application itself is left with the responsibility of implementing a fullscreen switch and ensuring predictable behavior.  This change at least makes getPosition and setPosition behave in a more predictable manner.

Window / Joystick button numbering doesn't always start at 0?
« on: September 26, 2012, 04:35:49 am »
I'm coming over to SFML from an SDL background.  I'm porting a tool that was written in SDL and I've come across unexpected behavior when dealing with joysticks (on Mac).  I've got a wired 360 controller from which SDL will deliver button events numbered 0 through 14.  The A, B, X, and Y buttons are the 0 through 3.  However, when using SFML, those buttons are mapped to 16 through 19.

SFML appears to number the 360 controller's buttons as 5 through 19 and has no buttons that correspond to 0 through 3.  All 15 of the buttons still work, but it's really weird to have a joystick whose first button is 5 instead of 0.  Is it possible I've done something wrong in code or is this common and expected behavior in SFML?

Pages: [1]