Пример #1
0
        private void SdlRunLoop()
        {
            Sdl.Event ev;

            while (Sdl.PollEvent(out ev) == 1)
            {
                switch (ev.Type)
                {
                case Sdl.EventType.Quit:
                    _isExiting++;
                    break;

                case Sdl.EventType.JoyDeviceAdded:
                    Joystick.AddDevice(ev.JoystickDevice.Which);
                    break;

                case Sdl.EventType.JoyDeviceRemoved:
                    Joystick.RemoveDevice(ev.JoystickDevice.Which);
                    break;

                case Sdl.EventType.ControllerDeviceRemoved:
                    GamePad.RemoveDevice(ev.ControllerDevice.Which);
                    break;

                case Sdl.EventType.ControllerButtonUp:
                case Sdl.EventType.ControllerButtonDown:
                case Sdl.EventType.ControllerAxisMotion:
                    GamePad.UpdatePacketInfo(ev.ControllerDevice.Which, ev.ControllerDevice.TimeStamp);
                    break;

                case Sdl.EventType.MouseWheel:
                    const int wheelDelta = 120;
                    Mouse.ScrollY += ev.Wheel.Y * wheelDelta;
                    Mouse.ScrollX += ev.Wheel.X * wheelDelta;
                    break;

                case Sdl.EventType.MouseMotion:
                    Window.MouseState.X = ev.Motion.X;
                    Window.MouseState.Y = ev.Motion.Y;
                    break;

                case Sdl.EventType.KeyDown:
                {
                    var key = KeyboardUtil.ToXna(ev.Key.Keysym.Sym);
                    if (!_keys.Contains(key))
                    {
                        _keys.Add(key);
                    }
                    char character = (char)ev.Key.Keysym.Sym;
                    _view.OnKeyDown(new InputKeyEventArgs(key));
                    if (char.IsControl(character))
                    {
                        _view.OnTextInput(new TextInputEventArgs(character, key));
                    }
                    break;
                }

                case Sdl.EventType.KeyUp:
                {
                    var key = KeyboardUtil.ToXna(ev.Key.Keysym.Sym);
                    _keys.Remove(key);
                    _view.OnKeyUp(new InputKeyEventArgs(key));
                    break;
                }

                case Sdl.EventType.TextInput:
                    if (_view.IsTextInputHandled)
                    {
                        int  len            = 0;
                        int  utf8character  = 0;  // using an int to encode multibyte characters longer than 2 bytes
                        byte currentByte    = 0;
                        int  charByteSize   = 0;  // UTF8 char lenght to decode
                        int  remainingShift = 0;
                        unsafe
                        {
                            while ((currentByte = Marshal.ReadByte((IntPtr)ev.Text.Text, len)) != 0)
                            {
                                // we're reading the first UTF8 byte, we need to check if it's multibyte
                                if (charByteSize == 0)
                                {
                                    if (currentByte < 192)
                                    {
                                        charByteSize = 1;
                                    }
                                    else if (currentByte < 224)
                                    {
                                        charByteSize = 2;
                                    }
                                    else if (currentByte < 240)
                                    {
                                        charByteSize = 3;
                                    }
                                    else
                                    {
                                        charByteSize = 4;
                                    }

                                    utf8character  = 0;
                                    remainingShift = 4;
                                }

                                // assembling the character
                                utf8character <<= 8;
                                utf8character  |= currentByte;

                                charByteSize--;
                                remainingShift--;

                                if (charByteSize == 0)                    // finished decoding the current character
                                {
                                    utf8character <<= remainingShift * 8; // shifting it to full UTF8 scope

                                    // SDL returns UTF8-encoded characters while C# char type is UTF16-encoded (and limited to the 0-FFFF range / does not support surrogate pairs)
                                    // so we need to convert it to Unicode codepoint and check if it's within the supported range
                                    int codepoint = UTF8ToUnicode(utf8character);

                                    if (codepoint >= 0 && codepoint < 0xFFFF)
                                    {
                                        _view.OnTextInput(new TextInputEventArgs((char)codepoint, KeyboardUtil.ToXna(codepoint)));
                                        // UTF16 characters beyond 0xFFFF are not supported (and would require a surrogate encoding that is not supported by the char type)
                                    }
                                }

                                len++;
                            }
                        }
                    }
                    break;

                case Sdl.EventType.WindowEvent:

                    switch (ev.Window.EventID)
                    {
                    case Sdl.Window.EventId.Resized:
                    case Sdl.Window.EventId.SizeChanged:
                        _view.ClientResize(ev.Window.Data1, ev.Window.Data2);
                        break;

                    case Sdl.Window.EventId.FocusGained:
                        IsActive = true;
                        break;

                    case Sdl.Window.EventId.FocusLost:
                        IsActive = false;
                        break;

                    case Sdl.Window.EventId.Moved:
                        _view.Moved();
                        break;

                    case Sdl.Window.EventId.Close:
                        _isExiting++;
                        break;
                    }
                    break;
                }
            }
        }
Пример #2
0
        private void SdlRunLoop()
        {
            Sdl.Event ev;

            while (Sdl.PollEvent(out ev) == 1)
            {
                if (ev.Type == Sdl.EventType.Quit)
                {
                    _isExiting++;
                }
                else if (ev.Type == Sdl.EventType.JoyDeviceAdded)
                {
                    Joystick.AddDevice(ev.JoystickDevice.Which);
                }
                else if (ev.Type == Sdl.EventType.ControllerDeviceRemoved)
                {
                    GamePad.RemoveDevice(ev.ControllerDevice.Which);
                }
                else if (ev.Type == Sdl.EventType.JoyDeviceRemoved)
                {
                    Joystick.RemoveDevice(ev.JoystickDevice.Which);
                }
                else if (ev.Type == Sdl.EventType.MouseWheel)
                {
                    const int wheelDelta = 120;
                    Mouse.ScrollY += ev.Wheel.Y * wheelDelta;
                    Mouse.ScrollX += ev.Wheel.X * wheelDelta;
                }
                else if (ev.Type == Sdl.EventType.MouseMotion)
                {
                    Window.MouseState.X = ev.Motion.X;
                    Window.MouseState.Y = ev.Motion.Y;
                }
                else if (ev.Type == Sdl.EventType.KeyDown)
                {
                    var key = KeyboardUtil.ToXna(ev.Key.Keysym.Sym);
                    if (!_keys.Contains(key))
                    {
                        _keys.Add(key);
                    }
                    char character = (char)ev.Key.Keysym.Sym;
                    if (char.IsControl(character))
                    {
                        _view.CallTextInput(character, key);
                    }
                }
                else if (ev.Type == Sdl.EventType.KeyUp)
                {
                    var key = KeyboardUtil.ToXna(ev.Key.Keysym.Sym);
                    _keys.Remove(key);
                }
                else if (ev.Type == Sdl.EventType.TextInput)
                {
                    int    len  = 0;
                    string text = String.Empty;
                    unsafe
                    {
                        while (Marshal.ReadByte((IntPtr)ev.Text.Text, len) != 0)
                        {
                            len++;
                        }
                        var buffer = new byte[len];
                        Marshal.Copy((IntPtr)ev.Text.Text, buffer, 0, len);
                        text = System.Text.Encoding.UTF8.GetString(buffer);
                    }
                    if (text.Length == 0)
                    {
                        continue;
                    }
                    foreach (var c in text)
                    {
                        var key = KeyboardUtil.ToXna((int)c);
                        _view.CallTextInput(c, key);
                    }
                }
                else if (ev.Type == Sdl.EventType.DropFile)
                {
                    _view.CallFileDrop(Sdl.GetString(ev.Drop.File));
                }
                else if (ev.Type == Sdl.EventType.WindowEvent)
                {
                    if (ev.Window.WindowID == _view.Id)
                    {
                        if (ev.Window.EventID == Sdl.Window.EventId.Resized || ev.Window.EventID == Sdl.Window.EventId.SizeChanged)
                        {
                            _view.ClientResize(ev.Window.Data1, ev.Window.Data2);
                        }
                        else if (ev.Window.EventID == Sdl.Window.EventId.FocusGained)
                        {
                            IsActive = true;
                        }
                        else if (ev.Window.EventID == Sdl.Window.EventId.FocusLost)
                        {
                            IsActive = false;
                        }
                        else if (ev.Window.EventID == Sdl.Window.EventId.Moved)
                        {
                            _view.Moved();
                        }
                        else if (ev.Window.EventID == Sdl.Window.EventId.Close)
                        {
                            _isExiting++;
                        }
                    }
                }
            }
        }
        private void PollSDLEvents()
        {
            Span <char> textEditingBuffer = stackalloc char[SDL.Keyboard.TextEditingEvent.TextSize];

            while (SDL.PollEvent(out SDL.Event ev) == 1)
            {
                switch (ev.Type)
                {
                case SDL.EventType.Quit:
                    Interlocked.Increment(ref _isExiting);
                    break;

                    #region Joystick

                case SDL.EventType.JoyDeviceAdded:
                    Joystick.AddDevice(ev.JoystickDevice.Which);
                    break;

                case SDL.EventType.JoyDeviceRemoved:
                    Joystick.RemoveDevice(ev.JoystickDevice.Which);
                    break;

                    #endregion

                    #region GameController

                case SDL.EventType.ControllerDeviceRemoved:
                    GamePad.RemoveDevice(ev.ControllerDevice.Which);
                    break;

                case SDL.EventType.ControllerButtonUp:
                case SDL.EventType.ControllerButtonDown:
                case SDL.EventType.ControllerAxisMotion:
                    GamePad.UpdatePacketInfo(ev.ControllerDevice.Which, ev.ControllerDevice.TimeStamp);
                    break;

                    #endregion

                    #region Mouse

                case SDL.EventType.MouseWheel:
                    _window.Mouse.ScrollX += ev.MouseWheel.X * MouseWheelDelta;
                    _window.Mouse.ScrollY += ev.MouseWheel.Y * MouseWheelDelta;
                    break;

                case SDL.EventType.MouseMotion:
                    _window.Mouse.State.X = ev.MouseMotion.X;
                    _window.Mouse.State.Y = ev.MouseMotion.Y;
                    break;

                    #endregion

                    #region Keyboard

                case SDL.EventType.KeyDown:
                {
                    bool hasMapping = KeyboardUtil.ToXna(ev.KeyboardKey.Keysym.Sym, out var key);
                    if (hasMapping)
                    {
                        if (!Keyboard._keysDown.Contains(key))
                        {
                            Keyboard._keysDown.Add(key);
                        }
                    }

                    // TODO: validate rune?
                    Rune.TryCreate(ev.KeyboardKey.Keysym.Sym, out var rune);

                    var inputEv = new TextInputEventArgs(rune, hasMapping ? key : (Keys?)null);
                    _window.OnKeyDown(inputEv);
                    break;
                }

                case SDL.EventType.KeyUp:
                {
                    bool hasMapping = KeyboardUtil.ToXna(ev.KeyboardKey.Keysym.Sym, out var key);
                    if (hasMapping)
                    {
                        Keyboard._keysDown.Remove(key);
                    }

                    // TODO: validate rune?
                    Rune.TryCreate(ev.KeyboardKey.Keysym.Sym, out var rune);

                    _window.OnKeyUp(new TextInputEventArgs(rune, hasMapping ? key : (Keys?)null));
                    break;
                }

                    #endregion

                    #region Text-Input/Editing

                case SDL.EventType.TextInput:
                    unsafe
                    {
                        var utf8 = new Span <byte>(ev.TextInput.Text, SDL.Keyboard.TextInputEvent.TextSize);
                        utf8 = SliceToNullTerminator(utf8);
                        while (!utf8.IsEmpty)
                        {
                            var status = Rune.DecodeFromUtf8(utf8, out Rune rune, out int bytesConsumed);
                            if (status != OperationStatus.Done)
                            {
                                // This should never occur if SDL gives use valid data.
                                throw new InvalidDataException("Failed to decode UTF-8 text input: " + status);
                            }
                            utf8 = utf8[bytesConsumed..];