Scripting: Basic gamepad support

This commit is contained in:
Vicki Pfau 2023-01-26 04:04:43 -08:00
parent a154690694
commit dfe2f62f16
3 changed files with 219 additions and 0 deletions

View File

@ -217,6 +217,14 @@ struct mScriptTriggerEvent {
bool state;
};
struct mScriptGamepad {
unsigned pad;
struct mScriptList axes;
struct mScriptList buttons;
struct mScriptList hats;
};
mSCRIPT_DECLARE_STRUCT(mScriptEvent);
mSCRIPT_DECLARE_STRUCT(mScriptKeyEvent);
mSCRIPT_DECLARE_STRUCT(mScriptMouseButtonEvent);
@ -227,10 +235,28 @@ mSCRIPT_DECLARE_STRUCT(mScriptGamepadHatEvent);
mSCRIPT_DECLARE_STRUCT(mScriptSensorEvent);
mSCRIPT_DECLARE_STRUCT(mScriptTriggerEvent);
mSCRIPT_DECLARE_STRUCT(mScriptGamepad);
void mScriptContextAttachInput(struct mScriptContext* context);
void mScriptContextFireEvent(struct mScriptContext*, struct mScriptEvent*);
int mScriptContextGamepadAttach(struct mScriptContext*, struct mScriptGamepad*);
bool mScriptContextGamepadDetach(struct mScriptContext*, int pad);
struct mScriptGamepad* mScriptContextGamepadLookup(struct mScriptContext*, int pad);
void mScriptGamepadInit(struct mScriptGamepad*);
void mScriptGamepadDeinit(struct mScriptGamepad*);
void mScriptGamepadSetAxisCount(struct mScriptGamepad*, unsigned);
void mScriptGamepadSetButtonCount(struct mScriptGamepad*, unsigned);
void mScriptGamepadSetHatCount(struct mScriptGamepad*, unsigned);
void mScriptGamepadSetAxis(struct mScriptGamepad*, unsigned, int16_t value);
void mScriptGamepadSetButton(struct mScriptGamepad*, unsigned, bool down);
void mScriptGamepadSetHat(struct mScriptGamepad*, unsigned, int direction);
int16_t mScriptGamepadGetAxis(struct mScriptGamepad*, unsigned);
bool mScriptGamepadGetButton(struct mScriptGamepad*, unsigned);
int mScriptGamepadGetHat(struct mScriptGamepad*, unsigned);
CXX_GUARD_END
#endif

View File

@ -30,6 +30,7 @@ static const struct mScriptType* eventTypes[mSCRIPT_EV_TYPE_MAX] = {
struct mScriptInputContext {
uint64_t seq;
struct Table activeKeys;
struct mScriptGamepad* activeGamepad;
};
static void _mScriptInputDeinit(struct mScriptInputContext*);
@ -43,6 +44,7 @@ mSCRIPT_DEFINE_STRUCT(mScriptInputContext)
mSCRIPT_DEFINE_STRUCT_DEINIT(mScriptInputContext)
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptInputContext, U64, seq)
mSCRIPT_DEFINE_STRUCT_METHOD(mScriptInputContext, isKeyActive)
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptInputContext, PCS(mScriptGamepad), activeGamepad)
mSCRIPT_DEFINE_END;
mSCRIPT_DEFINE_STRUCT(mScriptEvent)
@ -92,6 +94,12 @@ mSCRIPT_DEFINE_STRUCT(mScriptGamepadHatEvent)
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepadHatEvent, U8, direction)
mSCRIPT_DEFINE_END;
mSCRIPT_DEFINE_STRUCT(mScriptGamepad)
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepad, LIST, axes)
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepad, LIST, buttons)
mSCRIPT_DEFINE_STRUCT_MEMBER(mScriptGamepad, LIST, hats)
mSCRIPT_DEFINE_END;
void mScriptContextAttachInput(struct mScriptContext* context) {
struct mScriptInputContext* inputContext = calloc(1, sizeof(*inputContext));
struct mScriptValue* value = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mScriptInputContext));
@ -258,3 +266,147 @@ void mScriptContextFireEvent(struct mScriptContext* context, struct mScriptEvent
mScriptContextTriggerCallback(context, eventNames[event->type], &args);
mScriptListDeinit(&args);
}
int mScriptContextGamepadAttach(struct mScriptContext* context, struct mScriptGamepad* pad) {
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
if (!input) {
return false;
}
struct mScriptInputContext* inputContext = input->value.opaque;
if (inputContext->activeGamepad) {
return -1;
}
inputContext->activeGamepad = pad;
return 0;
}
bool mScriptContextGamepadDetach(struct mScriptContext* context, int pad) {
if (pad != 0) {
return false;
}
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
if (!input) {
return false;
}
struct mScriptInputContext* inputContext = input->value.opaque;
if (!inputContext->activeGamepad) {
return false;
}
inputContext->activeGamepad = NULL;
return true;
}
struct mScriptGamepad* mScriptContextGamepadLookup(struct mScriptContext* context, int pad) {
if (pad != 0) {
return NULL;
}
struct mScriptValue* input = mScriptContextGetGlobal(context, "input");
if (!input) {
return false;
}
struct mScriptInputContext* inputContext = input->value.opaque;
return inputContext->activeGamepad;
}
void mScriptGamepadInit(struct mScriptGamepad* gamepad) {
memset(gamepad, 0, sizeof(*gamepad));
mScriptListInit(&gamepad->axes, 8);
mScriptListInit(&gamepad->buttons, 1);
mScriptListInit(&gamepad->hats, 1);
}
void mScriptGamepadDeinit(struct mScriptGamepad* gamepad) {
mScriptListDeinit(&gamepad->axes);
mScriptListDeinit(&gamepad->buttons);
mScriptListDeinit(&gamepad->hats);
}
void mScriptGamepadSetAxisCount(struct mScriptGamepad* gamepad, unsigned count) {
if (count > UINT8_MAX) {
count = UINT8_MAX;
}
unsigned oldSize = mScriptListSize(&gamepad->axes);
mScriptListResize(&gamepad->axes, (ssize_t) count - oldSize);
unsigned i;
for (i = oldSize; i < count; ++i) {
*mScriptListGetPointer(&gamepad->axes, i) = mSCRIPT_MAKE_S16(0);
}
}
void mScriptGamepadSetButtonCount(struct mScriptGamepad* gamepad, unsigned count) {
if (count > UINT16_MAX) {
count = UINT16_MAX;
}
unsigned oldSize = mScriptListSize(&gamepad->buttons);
mScriptListResize(&gamepad->buttons, (ssize_t) count - oldSize);
unsigned i;
for (i = oldSize; i < count; ++i) {
*mScriptListGetPointer(&gamepad->buttons, i) = mSCRIPT_MAKE_BOOL(false);
}
}
void mScriptGamepadSetHatCount(struct mScriptGamepad* gamepad, unsigned count) {
if (count > UINT8_MAX) {
count = UINT8_MAX;
}
unsigned oldSize = mScriptListSize(&gamepad->hats);
mScriptListResize(&gamepad->hats, (ssize_t) count - oldSize);
unsigned i;
for (i = oldSize; i < count; ++i) {
*mScriptListGetPointer(&gamepad->hats, i) = mSCRIPT_MAKE_U8(0);
}
}
void mScriptGamepadSetAxis(struct mScriptGamepad* gamepad, unsigned id, int16_t value) {
if (id >= mScriptListSize(&gamepad->axes)) {
return;
}
mScriptListGetPointer(&gamepad->axes, id)->value.s32 = value;
}
void mScriptGamepadSetButton(struct mScriptGamepad* gamepad, unsigned id, bool down) {
if (id >= mScriptListSize(&gamepad->buttons)) {
return;
}
mScriptListGetPointer(&gamepad->buttons, id)->value.u32 = down;
}
void mScriptGamepadSetHat(struct mScriptGamepad* gamepad, unsigned id, int direction) {
if (id >= mScriptListSize(&gamepad->hats)) {
return;
}
mScriptListGetPointer(&gamepad->hats, id)->value.u32 = direction;
}
int16_t mScriptGamepadGetAxis(struct mScriptGamepad* gamepad, unsigned id) {
if (id >= mScriptListSize(&gamepad->axes)) {
return 0;
}
return mScriptListGetPointer(&gamepad->axes, id)->value.s32;
}
bool mScriptGamepadGetButton(struct mScriptGamepad* gamepad, unsigned id) {
if (id >= mScriptListSize(&gamepad->buttons)) {
return false;
}
return mScriptListGetPointer(&gamepad->buttons, id)->value.u32;
}
int mScriptGamepadGetHat(struct mScriptGamepad* gamepad, unsigned id) {
if (id >= mScriptListSize(&gamepad->hats)) {
return mSCRIPT_INPUT_DIR_NONE;
}
return mScriptListGetPointer(&gamepad->hats, id)->value.u32;
}

View File

@ -109,8 +109,49 @@ M_TEST_DEFINE(fireKey) {
mScriptContextDeinit(&context);
}
M_TEST_DEFINE(gamepadExport) {
SETUP_LUA;
struct mScriptGamepad m_gamepad;
mScriptGamepadInit(&m_gamepad);
TEST_PROGRAM("assert(not input.activeGamepad)");
assert_int_equal(mScriptContextGamepadAttach(&context, &m_gamepad), 0);
TEST_PROGRAM("assert(input.activeGamepad)");
TEST_PROGRAM("assert(#input.activeGamepad.axes == 0)");
TEST_PROGRAM("assert(#input.activeGamepad.buttons == 0)");
TEST_PROGRAM("assert(#input.activeGamepad.hats == 0)");
mScriptGamepadSetAxisCount(&m_gamepad, 1);
TEST_PROGRAM("assert(#input.activeGamepad.axes == 1)");
TEST_PROGRAM("assert(input.activeGamepad.axes[1] == 0)");
mScriptGamepadSetAxis(&m_gamepad, 0, 123);
TEST_PROGRAM("assert(input.activeGamepad.axes[1] == 123)");
mScriptGamepadSetButtonCount(&m_gamepad, 1);
TEST_PROGRAM("assert(#input.activeGamepad.buttons == 1)");
TEST_PROGRAM("assert(input.activeGamepad.buttons[1] == false)");
mScriptGamepadSetButton(&m_gamepad, 0, true);
TEST_PROGRAM("assert(input.activeGamepad.buttons[1] == true)");
mScriptGamepadSetHatCount(&m_gamepad, 1);
TEST_PROGRAM("assert(#input.activeGamepad.hats == 1)");
TEST_PROGRAM("assert(input.activeGamepad.hats[1] == C.INPUT_DIR.NONE)");
mScriptGamepadSetHat(&m_gamepad, 0, mSCRIPT_INPUT_DIR_NORTHWEST);
TEST_PROGRAM("assert(input.activeGamepad.hats[1] == C.INPUT_DIR.NORTHWEST)");
mScriptContextGamepadDetach(&context, 0);
TEST_PROGRAM("assert(not input.activeGamepad)");
mScriptGamepadDeinit(&m_gamepad);
mScriptContextDeinit(&context);
}
M_TEST_SUITE_DEFINE_SETUP_TEARDOWN(mScriptInput,
cmocka_unit_test(members),
cmocka_unit_test(seq),
cmocka_unit_test(fireKey),
cmocka_unit_test(gamepadExport),
)