add system for text input

pull/14/head
cosmonaut 2021-03-25 15:57:26 -07:00
parent ccefe570db
commit 984e30cc4c
3 changed files with 86 additions and 0 deletions

View File

@ -4,6 +4,7 @@ using MoonWorks.Audio;
using MoonWorks.Graphics; using MoonWorks.Graphics;
using MoonWorks.Input; using MoonWorks.Input;
using MoonWorks.Window; using MoonWorks.Window;
using System.Text;
namespace MoonWorks namespace MoonWorks
{ {
@ -107,6 +108,10 @@ namespace MoonWorks
case SDL.SDL_EventType.SDL_QUIT: case SDL.SDL_EventType.SDL_QUIT:
quit = true; quit = true;
break; break;
case SDL.SDL_EventType.SDL_TEXTINPUT:
HandleTextInput(_event);
break;
} }
} }
} }
@ -114,5 +119,40 @@ namespace MoonWorks
protected abstract void Update(double dt); protected abstract void Update(double dt);
protected abstract void Draw(double dt, double alpha); protected abstract void Draw(double dt, double alpha);
private void HandleTextInput(SDL2.SDL.SDL_Event evt)
{
// Based on the SDL2# LPUtf8StrMarshaler
unsafe
{
int bytes = MeasureStringLength(evt.text.text);
if (bytes > 0)
{
/* UTF8 will never encode more characters
* than bytes in a string, so bytes is a
* suitable upper estimate of size needed
*/
char* charsBuffer = stackalloc char[bytes];
int chars = Encoding.UTF8.GetChars(
evt.text.text,
bytes,
charsBuffer,
bytes
);
for (int i = 0; i < chars; i += 1)
{
Inputs.OnTextInput(charsBuffer[i]);
}
}
}
}
private unsafe static int MeasureStringLength(byte* ptr)
{
int bytes;
for (bytes = 0; *ptr != 0; ptr += 1, bytes += 1);
return bytes;
}
} }
} }

View File

@ -1,4 +1,5 @@
using SDL2; using SDL2;
using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace MoonWorks.Input namespace MoonWorks.Input
@ -10,6 +11,8 @@ namespace MoonWorks.Input
List<Gamepad> gamepads = new List<Gamepad>(); List<Gamepad> gamepads = new List<Gamepad>();
public static event Action<char> TextInput;
internal Inputs() internal Inputs()
{ {
Keyboard = new Keyboard(); Keyboard = new Keyboard();
@ -45,5 +48,13 @@ namespace MoonWorks.Input
{ {
return gamepads[slot]; return gamepads[slot];
} }
internal static void OnTextInput(char c)
{
if (TextInput != null)
{
TextInput(c);
}
}
} }
} }

View File

@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using SDL2; using SDL2;
@ -9,6 +10,28 @@ namespace MoonWorks.Input
private ButtonState[] Keys { get; } private ButtonState[] Keys { get; }
private int numKeys; private int numKeys;
private static readonly char[] TextInputCharacters = new char[]
{
(char) 2, // Home
(char) 3, // End
(char) 8, // Backspace
(char) 9, // Tab
(char) 13, // Enter
(char) 127, // Delete
(char) 22 // Ctrl+V (Paste)
};
private static readonly Dictionary<Keycode, int> TextInputBindings = new Dictionary<Keycode, int>()
{
{ Keycode.Home, 0 },
{ Keycode.End, 1 },
{ Keycode.Backspace, 2 },
{ Keycode.Tab, 3 },
{ Keycode.Return, 4 },
{ Keycode.Delete, 5 }
// Ctrl+V is special!
};
internal Keyboard() internal Keyboard()
{ {
SDL.SDL_GetKeyboardState(out numKeys); SDL.SDL_GetKeyboardState(out numKeys);
@ -28,6 +51,18 @@ namespace MoonWorks.Input
{ {
var keyDown = Marshal.ReadByte(keyboardState, keycode); var keyDown = Marshal.ReadByte(keyboardState, keycode);
Keys[keycode].Update(Conversions.ByteToBool(keyDown)); Keys[keycode].Update(Conversions.ByteToBool(keyDown));
if (Conversions.ByteToBool(keyDown))
{
if (TextInputBindings.TryGetValue((Keycode)keycode, out var textIndex))
{
Inputs.OnTextInput(TextInputCharacters[(textIndex)]);
}
else if (IsDown(Keycode.LeftControl) && (Keycode)keycode == Keycode.V)
{
Inputs.OnTextInput(TextInputCharacters[6]);
}
}
} }
} }