diff --git a/src/script/input.c b/src/script/input.c index fdb6593cb..23fc498e9 100644 --- a/src/script/input.c +++ b/src/script/input.c @@ -36,17 +36,21 @@ struct mScriptInputContext { static void _mScriptInputDeinit(struct mScriptInputContext*); static bool _mScriptInputIsKeyActive(const struct mScriptInputContext*, struct mScriptValue*); +static struct mScriptValue* _mScriptInputActiveKeys(const struct mScriptInputContext*); mSCRIPT_DECLARE_STRUCT(mScriptInputContext); mSCRIPT_DECLARE_STRUCT_VOID_METHOD(mScriptInputContext, _deinit, _mScriptInputDeinit, 0); mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, BOOL, isKeyActive, _mScriptInputIsKeyActive, 1, WRAPPER, key); +mSCRIPT_DECLARE_STRUCT_C_METHOD(mScriptInputContext, WLIST, activeKeys, _mScriptInputActiveKeys, 0); mSCRIPT_DEFINE_STRUCT(mScriptInputContext) mSCRIPT_DEFINE_STRUCT_DEINIT(mScriptInputContext) mSCRIPT_DEFINE_DOCSTRING("Sequence number of the next event to be emitted") mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptInputContext, U64, seq) - mSCRIPT_DEFINE_DOCSTRING("Check if a given keyboard key is currently held. The input can be either the printable character for a key, or the numerical Unicode codepoint") + mSCRIPT_DEFINE_DOCSTRING("Check if a given keyboard key is currently held. The input can be either the printable character for a key, the numerical Unicode codepoint, or a special value from C.KEY") mSCRIPT_DEFINE_STRUCT_METHOD(mScriptInputContext, isKeyActive) + mSCRIPT_DEFINE_DOCSTRING("Get a list of the currently active keys. The values are Unicode codepoints or special key values from C.KEY, not strings, so make sure to convert as needed") + mSCRIPT_DEFINE_STRUCT_METHOD(mScriptInputContext, activeKeys) mSCRIPT_DEFINE_DOCSTRING("The currently active gamepad, if any") mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptInputContext, PCS(mScriptGamepad), activeGamepad) mSCRIPT_DEFINE_END; @@ -346,6 +350,19 @@ bool _mScriptInputIsKeyActive(const struct mScriptInputContext* context, struct return down != NULL; } +static struct mScriptValue* _mScriptInputActiveKeys(const struct mScriptInputContext* context) { + struct mScriptValue* list = mScriptValueAlloc(mSCRIPT_TYPE_MS_LIST); + struct TableIterator iter; + if (!TableIteratorStart(&context->activeKeys, &iter)) { + return list; + } + do { + uint32_t key = TableIteratorGetKey(&context->activeKeys, &iter); + *mScriptListAppend(list->value.list) = mSCRIPT_MAKE_U32(key); + } while (TableIteratorNext(&context->activeKeys, &iter)); + return list; +} + static bool _updateKeys(struct mScriptContext* context, struct mScriptKeyEvent* event) { int offset = 0; switch (event->state) { diff --git a/src/script/test/input.c b/src/script/test/input.c index de3ae0e0c..08b6a3bf8 100644 --- a/src/script/test/input.c +++ b/src/script/test/input.c @@ -109,6 +109,28 @@ M_TEST_DEFINE(fireKey) { mScriptContextDeinit(&context); } +M_TEST_DEFINE(activeKeys) { + SETUP_LUA; + + TEST_PROGRAM("assert(#input:activeKeys() == 0)"); + + struct mScriptKeyEvent keyEvent = { + .d = { .type = mSCRIPT_EV_TYPE_KEY }, + .state = mSCRIPT_INPUT_STATE_DOWN, + .key = 'a' + }; + mScriptContextFireEvent(&context, &keyEvent.d); + TEST_PROGRAM("assert(#input:activeKeys() == 1)"); + TEST_PROGRAM("assert(input:activeKeys()[1] == string.byte('a'))"); + + keyEvent.state = mSCRIPT_INPUT_STATE_UP; + mScriptContextFireEvent(&context, &keyEvent.d); + + TEST_PROGRAM("assert(#input:activeKeys() == 0)"); + + mScriptContextDeinit(&context); +} + M_TEST_DEFINE(gamepadExport) { SETUP_LUA; @@ -153,5 +175,6 @@ M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptInput, cmocka_unit_test(members), cmocka_unit_test(seq), cmocka_unit_test(fireKey), + cmocka_unit_test(activeKeys), cmocka_unit_test(gamepadExport), )