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

Use glutin to replace sdl2 #35

Merged
merged 33 commits into from Nov 30, 2018
Merged

Use glutin to replace sdl2 #35

merged 33 commits into from Nov 30, 2018

Conversation

iceiix
Copy link
Owner

@iceiix iceiix commented Nov 29, 2018

@iceiix
Copy link
Owner Author

iceiix commented Nov 29, 2018

Initial results are promising, but have to understand DPI, see glutin documentation, dpi module: https://docs.rs/glutin/0.19.0/glutin/. Naively converting this SDL2 code:

let (width, height) = window.size();

to Glutin, converting the LogicalSize to PhysicalSize, since https://docs.rs/glutin/0.19.0/glutin/dpi/index.html says Your GPU has no awareness of the concept of logical pixels, and unless you like wasting pixel density, your framebuffer's size should be in physical pixels.:

let (width, height) = window.get_inner_size().unwrap().to_physical(game.dpi_factor).into();

causes everything to be scaled down by half, on a dpi=2 system:

screen shot 2018-11-28 at 6 19 21 pm

when it should be:

screen shot 2018-11-28 at 6 20 03 pm

Removing .to_physical() and using LogicalSize fixes the UI scaling, but the game area then only fills the lower-right quarter of the screen:

screen shot 2018-11-28 at 6 25 46 pm

Maybe this is 1854275 https://github.com/iceiix/steven/issues/22 rearing its head... SDL2 has drawable_size() and size() instead of PhysicalSize and LogicalSize. Or use logical/physical for different purposes? UI vs game? Same values are used in several calls:

        game.renderer.update_camera(width, height);

        game.console
            .lock()
            .unwrap()
            .tick(&mut ui_container, &game.renderer, delta, width as f64);
        ui_container.tick(&mut game.renderer, delta, width as f64, height as f64);
        game.renderer.tick(&mut game.server.world, delta, width, height);

@iceiix
Copy link
Owner Author

iceiix commented Nov 29, 2018

That's better:

screen shot 2018-11-28 at 6 33 59 pm

There's more work to be done on the conversion: events (keyboard: text, keycodes, mouse: motion, buttons), then removing sdl2, etc.

Glutin has separate WindowEvent::CursorMoved and
DeviceEvent::MouseMotion events, for absolute cursor and relative mouse
motion, respectively, instead of SDL's Event::MouseMotion for both.
@iceiix
Copy link
Owner Author

iceiix commented Nov 30, 2018

Implemented the mouse events, except for the glutin equivalent of SDL2's enabling "relative mouse mode":

                    if !mouse.relative_mouse_mode() {
                        mouse.set_relative_mouse_mode(true);

and disabling:

                    if mouse.relative_mouse_mode() {
                        mouse.set_relative_mouse_mode(false);
                    }

This is SDL_GetRelativeMouseMode and SDL_SetRelativeMouseMode, which does this:

While the mouse is in relative mode, the cursor is hidden, and the driver will try to report continuous motion in the current window. Only relative motion events will be delivered, the mouse position will not change.

What is the glutin equivalent? Window has a grab_cursor method, and also hide_cursor. Aside: why does Steven, using SDL2, check SDL_GetRelativeMouseMode before calling SDL_SetRelativeMouseMode? Is it needed? Not finding an equivalent "get grabbed" method in glutin, trying without it.

@iceiix
Copy link
Owner Author

iceiix commented Nov 30, 2018

The fix for #35 (comment) fixed most of the rendering, but the transparent rendering (such as water) only covers the lower quarter of the screen:

screen shot 2018-11-29 at 5 15 01 pm

… full size but the ui is still sized logically.
@iceiix
Copy link
Owner Author

iceiix commented Nov 30, 2018

Fixed screen shot 2018-11-29 at 7 23 01 pm

@iceiix
Copy link
Owner Author

iceiix commented Nov 30, 2018

Problems so far:

  1. (partial fix bec47d5) SDL2 supports changing vsync after the window is created, and Steven has an option to toggle it. Glutin doesn't currently, but there is an open request to do so: Allow changing vsync on a Window rust-windowing/glutin#693 Allow changing vsync on a Window. However, even if vsync cannot be changed dynamically, could still respect the setting on startup.

  2. (fixed in 18c9d40) Specific version of OpenGL is not requested, what is the Glutin equivalent of this code?

    let gl_attr = sdl_video.gl_attr();
    gl_attr.set_stencil_size(0);
    gl_attr.set_depth_size(24);
    gl_attr.set_context_major_version(3);
    gl_attr.set_context_minor_version(2);
    gl_attr.set_context_profile(sdl2::video::GLProfile::Core);

https://docs.rs/glutin/0.19.0/glutin/struct.GlAttributes.html

  1. Broken mouse controls on Ubuntu
    sdl2::hint::set_with_priority("SDL_MOUSE_RELATIVE_MODE_WARP", "1", &sdl2::hint::Hint::Override); 

was added in Thinkofname#73 Mouse controls broken on Linux, unable to look up, but in switching to glutin, the problem is back. See SDL2 bugs: https://bugzilla.libsdl.org/show_bug.cgi?id=2150 and https://bugzilla.libsdl.org/show_bug.cgi?id=2954 (new). Testing with glutin, the MouseMotion event is supposed to return a delta, but it returns absolute values in this configuration. Couldn't find an open issue on it, so opened one: https://github.com/tomaka/glutin/issues/1084. Possible to workaround? Maybe add keyboard camera controls?

  1. (fixed in 95f2065) Text input, typing into UI fields

Glutin equivalent of sdl2's Event::TextInput is DeviceEvent::Text, but:

            glutin::DeviceEvent::Text{codepoint} => {
                println!("text {}", codepoint);
                if !game.focused {
                    ui_container.key_type(game, codepoint);
                }
            },  

doesn't seem to ever get called when I type into a text field (using add server screen).

@iceiix
Copy link
Owner Author

iceiix commented Nov 30, 2018

winit implements DeviceEvent::Text, see https://github.com/tomaka/winit/blob/master/src/events.rs#L155

https://github.com/tomaka/winit/blob/aabf0e13b78e156aac3037c9051f49534195e489/CHANGELOG.md#version-0140-2018-05-09 says:

On Windows, implemented all variants of DeviceEvent other than Text.

rust-windowing/winit@fe2d37f

All variants other than Text have been implemented. While Text can be implemented using ToUnicode, that doesn't play nice with dead keys, IME, etc.

rust-windowing/winit#467

I excluded DeviceEvent::Text, since there doesn't seem to be any practical way to implement that to give you the same characters you'd expect from WindowEvent::ReceivedCharacter.

try using ReceivedCharacter instead

@iceiix
Copy link
Owner Author

iceiix commented Nov 30, 2018

Works decently well although there are some minor todos, even works on Windows. Only unported feature is clipboard handling, specifically, pasting with Ctrl-V in src/ui/mod.rs:

                    let clipboard = game.sdl.video().unwrap().clipboard();
                     if clipboard.has_clipboard_text() {
                         let text = clipboard.clipboard_text().unwrap();
                         self.input.push_str(&text);
                     }

winit plans to add a clipboard API but doesn't yet, there are alternative clipboard crates to try out: https://crates.io/search?q=clipboard

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.

None yet

1 participant