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.


Messages - TheMaskedFox

Pages: [1]
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.

http://fr.sfml-dev.org/forums/index.php?topic=9075.msg62994#msg62994

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.

2
I'm running this on OS X 10.7.4.  Two displays, secondary positioned to the left of main.  The window opens on the main display.  When I hit spacebar, the window jumps and ends up positioned across both displays, starting in the lower left of the secondary and carrying over to the main.  The window is mostly off the bottom of the displays.

Anytime I call getPosition and apply the output back into setPosition, the window should remain exactly where it is currently positioned.

Quote
int main(int argc, char* argv[])
{
    sf::Event event;
    sf::Window window(sf::VideoMode(320, 240), "Position Test");
    sf::Vector2i pos;

    while (window.isOpen()) {
        while (window.pollEvent(event)) {
            switch (event.type) {
                case sf::Event::Closed:
                    window.close();
                    break;
               
                case sf::Event::KeyPressed:
                    if (sf::Keyboard::Space == event.key.code) {
                        pos = window.getPosition();
                        window.setPosition(pos);
                    }
                    break;
                   
                default:
                    break;
            }
        }
    }
   
    return 0;
}

I managed to mostly resolve this in my fork of SFML.  Take a look at https://github.com/SFML/SFML/pull/295 to see my solution.

3
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.

Quote
////////////////////////////////////////////////////////////
-(NSPoint)position
{
    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.

EDIT:
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.

EDIT 2:
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.

4
Window / Re: Joystick button numbering doesn't always start at 0?
« on: October 02, 2012, 09:40:54 am »
I'll have a look when I've some free time (unfortunately not in the near future) at SDL code. But, tell me, which version of SDL did you try ?

It was SDL 2.0 (which I think is just 1.3 without the 1.2 compatibility...).

Nevermind that though.  I think I've found the problem and solved it.  I'm not a contributor to SFML, so I've got no idea what the proper process is for submitting a patch.  I would assume it starts with a fork on github.

In lieu of that, let me quickly explain what I did.  First off, I defined a sort predicate for the joystick buttons as:

Quote
bool JoystickButtonSortPredicate(IOHIDElementRef d1, IOHIDElementRef d2)
{
    return IOHIDElementGetUsage(d1) < IOHIDElementGetUsage(d2);
}

Then, after the for loop that goes through the elements, I added (truncated for-loop included):

Quote
    // Go through all connected elements.
    for (int i = 0; i < elementsCount; ++i) {
       ...
    }
   
    // Sort buttons according to HID Usage
    std::sort(m_buttons.begin(), m_buttons.end(), JoystickButtonSortPredicate);

In doing so, my buttons are all exactly where I expect them to be and mesh properly with SDL's interpretation of them.

5
Window / Re: Joystick button numbering doesn't always start at 0?
« on: October 02, 2012, 08:30:55 am »
Ok so I'll have to improve https://github.com/SFML/SFML/blob/master/src/SFML/Window/OSX/JoystickImpl.cpp#L210 I suppose. Thanks for the feedback.

I've been digging into SDL, SFML, and the source code for the driver I'm using (which is http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver).  Not being too familiar with any of the codebases, I'm not making much progress in figuring out why SDL sees the buttons as 0-15 and SFML sees them as 5 through 19.  It's a really weird "bug".  I find it highly unlikely that SDL specifically recognizes the 360 Mac driver and remaps 16, 17, 18, and 19 down to 0, 1, 2, and 3.  So that leaves me trying to determine why, when both SDL and SFML are looking at the same output from the same driver, they get two different button mappings.

I probably need to go through the task of hooking the SFML source into my Xcode project so that I can directly debug SFML's recognition of my controller.

6
Window / Re: Joystick button numbering doesn't always start at 0?
« on: October 02, 2012, 08:18:45 am »
hey. saw this post. I am also looking into using x360 controller input for my game. Haven't tried anything yet, may be its quite straightforward. I am curious to know how did you interface x360 input's with sfml? Does the sfml's joystick class directly reads from the USB port or wireless adapter or there is something extra that needs to be done?

In Mac, I had to install a third-party driver from http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/OsxDriver in order to use the 360 controller.  However, once the driver was installed, the 360 controller was recognized in SDL and SFML without any extra work.  It is treated like any other joystick.  In my case, I'm just watching for joystick events (JoystickButtonPressed, JoystickMoved) from pollEvent().  The only issue I've encountered is the button numbering one that this topic is about.

7
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]