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

Input rewrite #17

Open
marrub-- opened this issue Sep 26, 2016 · 9 comments
Open

Input rewrite #17

marrub-- opened this issue Sep 26, 2016 · 9 comments

Comments

@marrub--
Copy link
Contributor

needs regular inputs, probably buffered, IME support (should display ingame and not on system), and some way to network sync via magic

@marrub-- marrub-- self-assigned this Sep 26, 2016
@marrub-- marrub-- changed the title Text input Input additions Sep 21, 2017
@marrub--
Copy link
Contributor Author

marrub-- commented Sep 21, 2017

I need to rewrite the input system a bit, when I do there are several goals:

  • Text input support using UTF32
  • IME support
  • Make axes return a 3-dimensional fractional vector in scripts
  • Make axis API more usable
  • Make buttons and axes rebindable, and use up to 32 of them instead of limiting it to just 8
  • Probably other usability concerns

All of these are fairly simple, thankfully. The binding API should probably be a bit like UE4.

@marrub-- marrub-- changed the title Input additions Input rewrite Sep 27, 2017
@marrub--
Copy link
Contributor Author

I'm honestly having trouble thinking of what API this should have. The internals will have to be rewritten in accordance with it, so I can't really do anything with it until the API is more clear. Suggestions welcome, the goals above all need to be solved. The entire API looks like this right now (I've only changed some things for consistency):

DGE_Native DGE_Point3R DGE_Input_GetAxis(unsigned num);
DGE_Native unsigned DGE_Input_GetButtons(void);
DGE_Native DGE_Point2I DGE_Input_GetCursor(void);

@Kyle873
Copy link

Kyle873 commented Sep 29, 2017

Considering my own use-case, here's a jumbled mess of words about what I was thinking:

  • Straight polling/checking of keyboard/mouse/gamepad buttons and axis for debugging/prototyping and quick creation of input. Personally I wasn't a fan of how ZDoom did this with having to store the buttons first and then checking against that, it felt a bit cumbersome compared to most engines just having straight boolean functions to check if a given key is pressed, released or held. This might just be a personal preference thing, though.
  • Virtual buttons and axis that can be (re-)binded onto any logical input device's buttons/axis to perform actions and/or functions. Ultimately, I would say there should be an infinite amount of virtual buttons/axis that can be created so that the user doesn't run into the kind of horrible situation you could like say with ZDoom only having the 4 user keys. This became a problem for me personally.
  • Text input could maybe be some sort of function where when called, it begins monitoring keypresses and shoves them into a given buffer so that you can utilize that for drawing or whatever you want to do with the string, then another function which ends the monitoring process. That's just one idea though and I don't know how valid or useful that'd be in actual use. I haven't worked with full text input much personally outside of LOVE which had a specific callback function handle it, maybe that could be another route to go too is to make it some sort of callback?
  • The cursor's current position should be able to be obtained in both screen space and world space.

For both direct and virtual input, there should probably be separate ways to check for a button being pressed, released and held, because all 3 states have different use cases.

Personally, I don't really use an IME nor know how they function internally or are implemented, so I can't speak much to that part.

@marrub--
Copy link
Contributor Author

marrub-- commented Sep 29, 2017

IMEs basically translate keyboard inputs to a buffer, which is then translated and then finalized into a completed input.

For example, kyouhaiitenkidesuna becomes きょうはいいてんきですな as you type, and then the user can press spacebar when they want to change it into a different possible variation like きょうはいいてんきですな -> 今日は良い天気ですな. During this state (called henkan) you can press spacebar for more choices, enter to complete the input, and whatever else the IME itself implements.

Virtual inputs

This should be its own issue really, considering its complexity. The biggest question is, as usual, "where do we store this information?" This is entirely a user option, so either we make a user configuration format in-engine or we do it in scripts with a native like DGE_Input_SetBind.

Text input

help my brain
I don't know at all how to do this, I don't know how other engines do this. I'll have to look into it, especially because this needs to be part of InputSource, which is networked.

Cursor position

There's one for world coordinates currently. Adding one for screen coordinates would be easy, but I don't see the use for it as all rendering is done in world coordinates.

Direct key checking

I don't know about this because it's potentially hard to network. It could work, but unless we can think of a way to network it correctly (without eating bandwidth) its use would have to be discouraged.

Button state checking

I think it would be best to change the button API from:

DGE_Native unsigned DGE_Input_GetButtons(void);

To:

enum // DGE_ButtonState
{
   DGE_Button_Clear, // button is up
   DGE_Button_Down,  // button has just been pressed
   DGE_Button_Held,  // button is being held
   DGE_Button_Up     // button has just been released
};

DGE_Native int DGE_Input_GetButtonState(unsigned btn);

Which kills two birds with one stone: You now have 4294967295 buttons, and you can get their individual states.

Axes

I think the way we handle this is already pretty good, besides the internals. You can get 4294967295 axes, and all of them return 3D input. (Yes, trust me, some devices have 3D input.)

@Kyle873
Copy link

Kyle873 commented Sep 29, 2017

Virtual inputs

I was expecting a native actually, I didn't even consider a format like KEYCONF or something. Which is the better option I guess could also depend on the scope/size of the project, so maybe having both wouldn't be a bad idea? A native in script could be useful for the use-casing of what I describe below in direct key checking.

Text input

Yeah, I doubt I'll be any help there. I have no idea how that works internally besides saying to go check out how other engines implement it I guess.

Cursor position

Ah right, that's a good point. Will it still have some use in terms of building a GUI, though?

Direct key checking

If virtual keys are quick and easy to add/create, then I don't really see this as needing to be necessary, especially if networking them would be a concern. My whole argument for having it in the first place stems from just "needing a quick or rough input check for something that may be debugging/testing/etc related", not to actually be used in any sort of final product or release.

Button state checking

Yeah, I approve of this for sure.

Axes

Yeah, I know. the DS4 exposes it's gyro and such IIRC so in theory that would totally be usable as an axis input if you wanted to do some crazy shit with input devices that support it.

@marrub--
Copy link
Contributor Author

Will it still have some use in terms of building a GUI, though?

Nope, because the GUI is also world coordinates. The GUI I'm writing right now uses the GetCursorPos function as-is, actually.

A native in script could be useful for the use-casing of what I describe below in direct key checking.

That's good, it would probably be best to just have a native set like this then:

DGE_Native void DGE_Input_SetBindKey(unsigned btn, int ch);
DGE_Native void DGE_Input_SetBindPad(unsigned btn, int num); // takes an enum that has common controller button names
DGE_Native void DGE_Input_SetAxisKey(unsigned axis, int chFrwd, int chBack, int chLeft, int chRght);
DGE_Native void DGE_Input_SetAxisPad(unsigned axis, int num); // takes an enum that has common controller axis names

And the user would provide their own config file format then. If we in the future add an internal config format this wouldn't clash.

@DavidPH
Copy link
Contributor

DavidPH commented Sep 29, 2017

Do remember that any rewrite of the input API needs to include specifying what player to get input for.

Also, as far as extension buttons, I definitely like the idea of allowing arbitrary extra buttons to be defined. And a step further, I wonder if we even want to have "builtin" buttons. That way games with very few needed buttons would be more easily optimized by the netcode, etc. That said, buttons should be defined statically, in either GAMEDEFS or CODEDEFS.

@marrub--
Copy link
Contributor Author

GAMEDEFS could definitely have that, as it's entirely static data that shouldn't be able to change (without recompiling of course.) So you'd basically just be defining the amount of bindable keys and axes.

@marrub--
Copy link
Contributor Author

marrub-- commented Oct 5, 2017

Partially done in 9e3e31a now. This is the final API unless there are any objections:

enum // DGE_Axis
{
   DGE_Axis_Up,
   DGE_Axis_Down,
   DGE_Axis_Left,
   DGE_Axis_Right,
   DGE_Axis_Forward,
   DGE_Axis_Backward,
};

enum // DGE_ButtonState
{
   DGE_Button_Down    = 1 << 0,
   DGE_Button_WasDown = 1 << 1,
   DGE_Button_Hold    = DGE_Button_Down | DGE_Button_WasDown,
   DGE_Button_Release = DGE_Button_WasDown,
   DGE_Button_Press   = DGE_Button_Down,
};

enum // DGE_Key
{
   DGE_Key_Backspace = '\b',
   DGE_Key_Tab       = '\t',
   DGE_Key_Return    = '\r',
   DGE_Key_Escape    = '\033',
   DGE_Key_Delete    = '\177',

   DGE_Key_Special  = 0x40000000,
   DGE_Key_Capslock = DGE_Key_Special + 0x39,

   DGE_Key_F1, DGE_Key_F2,  DGE_Key_F3,  DGE_Key_F4,
   DGE_Key_F5, DGE_Key_F6,  DGE_Key_F7,  DGE_Key_F8,
   DGE_Key_F9, DGE_Key_F10, DGE_Key_F11, DGE_Key_F12,
   DGE_Key_SysRq,
   DGE_Key_ScrollLock,
   DGE_Key_Pause,

   DGE_Key_Insert, DGE_Key_Home, DGE_Key_PageUp,
                   DGE_Key_End,  DGE_Key_PageDown,

   DGE_Key_Right, DGE_Key_Left, DGE_Key_Down, DGE_Key_Up,

   DGE_Key_NumLock,
   DGE_Key_KP_Div, DGE_Key_KP_Mul, DGE_Key_KP_Sub, DGE_Key_KP_Add,
   DGE_Key_KP_Enter,
   DGE_Key_KP_1, DGE_Key_KP_2, DGE_Key_KP_3,
   DGE_Key_KP_4, DGE_Key_KP_5, DGE_Key_KP_6,
   DGE_Key_KP_7, DGE_Key_KP_8, DGE_Key_KP_9,
   DGE_Key_KP_0, DGE_Key_KP_Dot
};

enum // DGE_MouseButton
{
   DGE_Mouse_Left,
   DGE_Mouse_Middle,
   DGE_Mouse_Right,
   DGE_Mouse_Extra1,
   DGE_Mouse_Extra2,
   DGE_Mouse_Extra3,
   DGE_Mouse_Extra4
};

enum // DGE_PadControl
{
   DGE_Pad_A,
   DGE_Pad_B,
   DGE_Pad_X,
   DGE_Pad_Y,
   DGE_Pad_Back,
   DGE_Pad_Menu,
   DGE_Pad_Start,
   DGE_Pad_StickLeft,
   DGE_Pad_StickRight,
   DGE_Pad_ShoulderLeft,
   DGE_Pad_ShoulderRight,
   DGE_Pad_DPadUp,
   DGE_Pad_DPadDown,
   DGE_Pad_DPadLeft,
   DGE_Pad_DPadRight,
   DGE_Pad_LStickUp,
   DGE_Pad_LStickDown,
   DGE_Pad_LStickLeft,
   DGE_Pad_LStickRight,
   DGE_Pad_RStickUp,
   DGE_Pad_RStickDown,
   DGE_Pad_RStickLeft,
   DGE_Pad_RStickRight,
   DGE_Pad_TriggerLeft,
   DGE_Pad_TriggerRight
};

DGE_Native DGE_Point3R DGE_Input_GetAxis(unsigned player, unsigned num);
DGE_Native unsigned DGE_Input_GetButton(unsigned player, unsigned btn);
DGE_Native DGE_Point2I DGE_Input_GetCursor(unsigned player);
DGE_Native void DGE_Input_SetAxisKey(unsigned num, unsigned axis, int set);
DGE_Native void DGE_Input_SetAxisPad(unsigned num, unsigned axis, unsigned set);
DGE_Native void DGE_Input_SetAxisMouse(unsigned num, unsigned axis, unsigned set);
DGE_Native void DGE_Input_SetBindKey(unsigned btn, int ch);
DGE_Native void DGE_Input_SetBindPad(unsigned btn, unsigned num);
DGE_Native void DGE_Input_SetBindMouse(unsigned btn, unsigned num);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants