/* Copyright (c) 2014 Alex Diener This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Alex Diener alex@ludobloom.com */ #include "inputcontroller/InputMap.h" #include "stem_core.h" #include #define stemobject_implementation InputMap stemobject_vtable_begin(); stemobject_vtable_entry(dispose); stemobject_vtable_end(); InputMap * InputMap_create() { stemobject_create_implementation(init) } bool InputMap_init(InputMap * self) { call_super(init, self); self->keyboardBindingCount = 0; self->keyboardBindings = NULL; self->keyboardBindingWithModifiersCount = 0; self->keyboardBindingsWithModifiers = NULL; self->keyModifierBindingCount = 0; self->keyModifierBindings = NULL; self->mouseButtonBindingCount = 0; self->mouseButtonBindings = NULL; self->mouseScrollBindingCount = 0; self->mouseScrollBindings = NULL; self->mouseMotion1DBindingCount = 0; self->mouseMotion1DBindings = NULL; self->mouseMotion2DBindingCount = 0; self->mouseMotion2DBindings = NULL; self->gamepadPhysicalMapCount = 0; self->gamepadPhysicalMaps = NULL; self->gamepadAliasCount = 0; self->gamepadAliases = NULL; self->gamepadLogicalMap.buttonActionBindingCount = 0; self->gamepadLogicalMap.buttonActionBindings = NULL; self->gamepadLogicalMap.axisActionBindingCount = 0; self->gamepadLogicalMap.axisActionBindings = NULL; self->gamepadLogicalMap.axisMotion1DBindingCount = 0; self->gamepadLogicalMap.axisMotion1DBindings = NULL; self->gamepadLogicalMap.axisMotion2DBindingCount = 0; self->gamepadLogicalMap.axisMotion2DBindings = NULL; return true; } void InputMap_dispose(InputMap * self) { free(self->keyboardBindings); free(self->keyboardBindingsWithModifiers); free(self->keyModifierBindings); free(self->mouseButtonBindings); free(self->mouseScrollBindings); free(self->mouseMotion1DBindings); free(self->mouseMotion2DBindings); for (unsigned int gamepadPhysicalMapIndex = 0; gamepadPhysicalMapIndex < self->gamepadPhysicalMapCount; gamepadPhysicalMapIndex++) { free(self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings); free(self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings); free(self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings); } free(self->gamepadPhysicalMaps); free(self->gamepadAliases); free(self->gamepadLogicalMap.buttonActionBindings); free(self->gamepadLogicalMap.axisActionBindings); free(self->gamepadLogicalMap.axisMotion1DBindings); free(self->gamepadLogicalMap.axisMotion2DBindings); call_super(dispose, self); } InputMap * InputMap_deserialize(compat_type(DeserializationContext *) deserializationContext, bool tolerateErrors) { stemobject_deserialize_implementation(loadSerializedData, tolerateErrors) } static bool isContainerFailStatus(int status) { return status == SERIALIZATION_ERROR_END_OF_CONTAINER || status == SERIALIZATION_ERROR_KEY_NOT_FOUND || status == SERIALIZATION_ERROR_INCORRECT_TYPE || status == SERIALIZATION_ERROR_NULL_KEY || status == SERIALIZATION_ERROR_MULTIPLE_TOP_LEVEL_CONTAINERS; } #define commitAtom(atom) atom = Atom_fromString(atom) bool InputMap_loadSerializedData(InputMap * self, compat_type(DeserializationContext *) deserializationContext, bool tolerateErrors) { DeserializationContext * context = deserializationContext; call_virtual(beginStructure, context, "input_map"); const char * formatType = call_virtual(readString, context, "format_type"); if (context->status != SERIALIZATION_ERROR_OK || strcmp(formatType, INPUT_MAP_SERIALIZATION_FORMAT_TYPE)) { return false; } uint16_t formatVersion = call_virtual(readUInt16, context, "format_version"); if (context->status != SERIALIZATION_ERROR_OK || (formatVersion > INPUT_MAP_SERIALIZATION_FORMAT_VERSION || formatVersion < 3)) { return false; } struct InputMap_keyboardActionBinding * keyboardBindings = NULL; unsigned int keyboardBindingCount = call_virtual(beginArray, context, "keyboard_bindings"); if (!isContainerFailStatus(context->status)) { if (keyboardBindingCount > 0) { keyboardBindings = malloc(keyboardBindingCount * sizeof(*keyboardBindings)); for (unsigned int bindingIndex = 0; bindingIndex < keyboardBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); keyboardBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); keyboardBindings[bindingIndex].keyCode = call_virtual(readUInt32, context, "key_code"); call_virtual(endStructure, context); } } call_virtual(endArray, context); } unsigned int keyboardBindingWithModifiersCount = 0; struct InputMap_keyboardActionBindingWithModifiers * keyboardBindingsWithModifiers = NULL; unsigned int keyModifierBindingCount = 0; struct InputMap_keyModifierActionBinding * keyModifierBindings = NULL; unsigned int mouseButtonBindingCount = 0; struct InputMap_mouseButtonBinding * mouseButtonBindings = NULL; unsigned int mouseScrollBindingCount = 0; struct InputMap_mouseScrollBinding * mouseScrollBindings = NULL; unsigned int mouseMotion1DBindingCount = 0; struct InputMap_mouseMotion1DBinding * mouseMotion1DBindings = NULL; unsigned int mouseMotion2DBindingCount = 0; struct InputMap_mouseMotion2DBinding * mouseMotion2DBindings = NULL; if (formatVersion > 4) { if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } keyboardBindingWithModifiersCount = call_virtual(beginArray, context, "keyboard_bindings_with_modifiers"); if (!isContainerFailStatus(context->status)) { if (keyboardBindingWithModifiersCount > 0) { keyboardBindingsWithModifiers = malloc(keyboardBindingWithModifiersCount * sizeof(*keyboardBindingsWithModifiers)); for (unsigned int bindingIndex = 0; bindingIndex < keyboardBindingWithModifiersCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); keyboardBindingsWithModifiers[bindingIndex].actionID = call_virtual(readString, context, "action"); keyboardBindingsWithModifiers[bindingIndex].keyCode = call_virtual(readUInt32, context, "key_code"); keyboardBindingsWithModifiers[bindingIndex].modifierFlags = call_virtual(readUInt8, context, "modifiers"); call_virtual(endStructure, context); } } call_virtual(endArray, context); } if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } keyModifierBindingCount = call_virtual(beginArray, context, "key_modifier_bindings"); if (!isContainerFailStatus(context->status)) { if (keyModifierBindingCount > 0) { keyModifierBindings = malloc(keyModifierBindingCount * sizeof(*keyModifierBindings)); for (unsigned int bindingIndex = 0; bindingIndex < keyModifierBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); keyModifierBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); keyModifierBindings[bindingIndex].modifierBit = call_virtual(readUInt8, context, "modifier"); call_virtual(endStructure, context); } } call_virtual(endArray, context); } if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } mouseButtonBindingCount = call_virtual(beginArray, context, "mouse_buttons"); if (!isContainerFailStatus(context->status)) { if (mouseButtonBindingCount > 0) { mouseButtonBindings = malloc(mouseButtonBindingCount * sizeof(*mouseButtonBindings)); for (unsigned int bindingIndex = 0; bindingIndex < mouseButtonBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); mouseButtonBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); mouseButtonBindings[bindingIndex].buttonNumber = call_virtual(readUInt8, context, "button"); call_virtual(endStructure, context); } } call_virtual(endArray, context); } if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } mouseScrollBindingCount = call_virtual(beginArray, context, "mouse_scroll"); if (!isContainerFailStatus(context->status)) { if (mouseScrollBindingCount > 0) { mouseScrollBindings = malloc(mouseScrollBindingCount * sizeof(*mouseScrollBindings)); for (unsigned int bindingIndex = 0; bindingIndex < mouseScrollBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); mouseScrollBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); mouseScrollBindings[bindingIndex].directionX = call_virtual(readInt8, context, "direction_x"); mouseScrollBindings[bindingIndex].directionY = call_virtual(readInt8, context, "direction_y"); call_virtual(endStructure, context); } } call_virtual(endArray, context); } if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } mouseMotion1DBindingCount = call_virtual(beginArray, context, "mouse_motion_1d"); if (!isContainerFailStatus(context->status)) { if (mouseMotion1DBindingCount > 0) { mouseMotion1DBindings = malloc(mouseMotion1DBindingCount * sizeof(*mouseMotion1DBindings)); for (unsigned int bindingIndex = 0; bindingIndex < mouseMotion1DBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); mouseMotion1DBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); mouseMotion1DBindings[bindingIndex].axisNumber = call_virtual(readUInt8, context, "axis"); call_virtual(endStructure, context); } } call_virtual(endArray, context); } if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } mouseMotion2DBindingCount = call_virtual(beginArray, context, "mouse_motion_2d"); if (!isContainerFailStatus(context->status)) { if (mouseMotion2DBindingCount > 0) { mouseMotion2DBindings = malloc(mouseMotion2DBindingCount * sizeof(*mouseMotion2DBindings)); for (unsigned int bindingIndex = 0; bindingIndex < mouseMotion2DBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); mouseMotion2DBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); call_virtual(endStructure, context); } } call_virtual(endArray, context); } } if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } struct InputMap_gamepadPhysicalMap * gamepadPhysicalMaps = NULL; unsigned int gamepadPhysicalMapCount = call_virtual(beginArray, context, "gamepad_maps"); if (!isContainerFailStatus(context->status)) { if (gamepadPhysicalMapCount > 0) { gamepadPhysicalMaps = malloc(gamepadPhysicalMapCount * sizeof(*gamepadPhysicalMaps)); for (unsigned int gamepadPhysicalMapIndex = 0; gamepadPhysicalMapIndex < gamepadPhysicalMapCount; gamepadPhysicalMapIndex++) { call_virtual(beginStructure, context, NULL); gamepadPhysicalMaps[gamepadPhysicalMapIndex].vendorID = call_virtual(readInt32, context, "vendor_id"); gamepadPhysicalMaps[gamepadPhysicalMapIndex].productID = call_virtual(readInt32, context, "product_id"); gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindingCount = call_virtual(beginDictionary, context, "button_bindings"); gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings = NULL; if (gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindingCount > 0) { gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings = malloc(gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindingCount * sizeof(*gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings)); for (unsigned int bindingIndex = 0; bindingIndex < gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindingCount; bindingIndex++) { const char * actionID = call_virtual(readNextDictionaryKey, context); gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings[bindingIndex].actionID = actionID; gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings[bindingIndex].buttonID = call_virtual(readUInt32, context, actionID); } } call_virtual(endDictionary, context); gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindingCount = call_virtual(beginArray, context, "axis_bindings"); gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings = NULL; if (gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindingCount > 0) { gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings = malloc(gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindingCount * sizeof(*gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings)); for (unsigned int bindingIndex = 0; bindingIndex < gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings[bindingIndex].axisID = call_virtual(readUInt32, context, "axis_id"); gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings[bindingIndex].activateThreshold = call_virtual(readFloat, context, formatVersion == 3 ? "trigger_threshold" : "activate_threshold"); gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings[bindingIndex].releaseThreshold = call_virtual(readFloat, context, "release_threshold"); call_virtual(endStructure, context); } } call_virtual(endArray, context); gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindingCount = 0; gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings = NULL; if (formatVersion > 4) { gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindingCount = call_virtual(beginArray, context, "axis_motion_bindings"); if (gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindingCount > 0) { gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings = malloc(gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindingCount * sizeof(*gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings)); for (unsigned int bindingIndex = 0; bindingIndex < gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings[bindingIndex].axisID = call_virtual(readUInt32, context, "axis_id"); call_virtual(endStructure, context); } } call_virtual(endArray, context); } call_virtual(endStructure, context); } } call_virtual(endArray, context); } struct InputMap_gamepadLogicalMap gamepadLogicalMap = {0, NULL, 0, NULL, 0, NULL, 0, NULL}; if (formatVersion > 4) { Serialization_enumKeyValue gamepadElementEnumValues[] = GAMEPAD_ELEMENT_ENUM_VALUES; if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } gamepadLogicalMap.buttonActionBindingCount = call_virtual(beginArray, context, "button_actions"); if (!isContainerFailStatus(context->status)) { if (gamepadLogicalMap.buttonActionBindingCount > 0) { gamepadLogicalMap.buttonActionBindings = malloc(gamepadLogicalMap.buttonActionBindingCount * sizeof(*gamepadLogicalMap.buttonActionBindings)); for (unsigned int bindingIndex = 0; bindingIndex < gamepadLogicalMap.buttonActionBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); gamepadLogicalMap.buttonActionBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); gamepadLogicalMap.buttonActionBindings[bindingIndex].elementID = call_virtual(readEnumeration, context, "element", sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); call_virtual(endStructure, context); } } call_virtual(endArray, context); } if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } gamepadLogicalMap.axisActionBindingCount = call_virtual(beginArray, context, "axis_actions"); if (!isContainerFailStatus(context->status)) { if (gamepadLogicalMap.axisActionBindingCount > 0) { gamepadLogicalMap.axisActionBindings = malloc(gamepadLogicalMap.axisActionBindingCount * sizeof(*gamepadLogicalMap.axisActionBindings)); for (unsigned int bindingIndex = 0; bindingIndex < gamepadLogicalMap.axisActionBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); gamepadLogicalMap.axisActionBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); gamepadLogicalMap.axisActionBindings[bindingIndex].elementID = call_virtual(readEnumeration, context, "element", sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); gamepadLogicalMap.axisActionBindings[bindingIndex].direction = call_virtual(readInt8, context, "direction"); call_virtual(endStructure, context); } } call_virtual(endArray, context); } if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } gamepadLogicalMap.axisMotion1DBindingCount = call_virtual(beginArray, context, "axis_motions_1d"); if (!isContainerFailStatus(context->status)) { if (gamepadLogicalMap.axisMotion1DBindingCount > 0) { gamepadLogicalMap.axisMotion1DBindings = malloc(gamepadLogicalMap.axisMotion1DBindingCount * sizeof(*gamepadLogicalMap.axisMotion1DBindings)); for (unsigned int bindingIndex = 0; bindingIndex < gamepadLogicalMap.axisMotion1DBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); gamepadLogicalMap.axisMotion1DBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); gamepadLogicalMap.axisMotion1DBindings[bindingIndex].elementID = call_virtual(readEnumeration, context, "element", sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); call_virtual(endStructure, context); } } call_virtual(endArray, context); } if (tolerateErrors) { context->status = SERIALIZATION_ERROR_OK; } gamepadLogicalMap.axisMotion2DBindingCount = call_virtual(beginArray, context, "axis_motions_2d"); if (!isContainerFailStatus(context->status)) { if (gamepadLogicalMap.axisMotion2DBindingCount > 0) { gamepadLogicalMap.axisMotion2DBindings = malloc(gamepadLogicalMap.axisMotion2DBindingCount * sizeof(*gamepadLogicalMap.axisMotion2DBindings)); for (unsigned int bindingIndex = 0; bindingIndex < gamepadLogicalMap.axisMotion2DBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); gamepadLogicalMap.axisMotion2DBindings[bindingIndex].actionID = call_virtual(readString, context, "action"); gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDX = call_virtual(readEnumeration, context, "element_x", sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDY = call_virtual(readEnumeration, context, "element_y", sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); call_virtual(endStructure, context); } } call_virtual(endArray, context); } } call_virtual(endStructure, context); if (context->status != SERIALIZATION_ERROR_OK && (!tolerateErrors || !isContainerFailStatus(context->status))) { free(keyboardBindings); for (unsigned int gamepadPhysicalMapIndex = 0; gamepadPhysicalMapIndex < gamepadPhysicalMapCount; gamepadPhysicalMapIndex++) { free(gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings); free(gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings); free(gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings); } free(gamepadPhysicalMaps); free(gamepadLogicalMap.buttonActionBindings); free(gamepadLogicalMap.axisActionBindings); free(gamepadLogicalMap.axisMotion1DBindings); free(gamepadLogicalMap.axisMotion2DBindings); return false; } for (unsigned int bindingIndex = 0; bindingIndex < keyboardBindingCount; bindingIndex++) { commitAtom(keyboardBindings[bindingIndex].actionID); } for (unsigned int gamepadPhysicalMapIndex = 0; gamepadPhysicalMapIndex < gamepadPhysicalMapCount; gamepadPhysicalMapIndex++) { for (unsigned int bindingIndex = 0; bindingIndex < gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindingCount; bindingIndex++) { commitAtom(gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings[bindingIndex].actionID); } for (unsigned int bindingIndex = 0; bindingIndex < gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindingCount; bindingIndex++) { commitAtom(gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings[bindingIndex].actionID); } for (unsigned int bindingIndex = 0; bindingIndex < gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindingCount; bindingIndex++) { commitAtom(gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings[bindingIndex].actionID); } } for (unsigned int bindingIndex = 0; bindingIndex < gamepadLogicalMap.buttonActionBindingCount; bindingIndex++) { commitAtom(gamepadLogicalMap.buttonActionBindings[bindingIndex].actionID); } for (unsigned int bindingIndex = 0; bindingIndex < gamepadLogicalMap.axisActionBindingCount; bindingIndex++) { commitAtom(gamepadLogicalMap.axisActionBindings[bindingIndex].actionID); } for (unsigned int bindingIndex = 0; bindingIndex < gamepadLogicalMap.axisMotion1DBindingCount; bindingIndex++) { commitAtom(gamepadLogicalMap.axisMotion1DBindings[bindingIndex].actionID); } for (unsigned int bindingIndex = 0; bindingIndex < gamepadLogicalMap.axisMotion2DBindingCount; bindingIndex++) { commitAtom(gamepadLogicalMap.axisMotion2DBindings[bindingIndex].actionID); } InputMap_init(self); self->keyboardBindingCount = keyboardBindingCount; self->keyboardBindings = keyboardBindings; self->keyboardBindingWithModifiersCount = keyboardBindingWithModifiersCount; self->keyboardBindingsWithModifiers = keyboardBindingsWithModifiers; self->keyModifierBindingCount = keyModifierBindingCount; self->keyModifierBindings = keyModifierBindings; self->mouseButtonBindingCount = mouseButtonBindingCount; self->mouseButtonBindings = mouseButtonBindings; self->mouseScrollBindingCount = mouseScrollBindingCount; self->mouseScrollBindings = mouseScrollBindings; self->mouseMotion1DBindingCount = mouseMotion1DBindingCount; self->mouseMotion1DBindings = mouseMotion1DBindings; self->mouseMotion2DBindingCount = mouseMotion2DBindingCount; self->mouseMotion2DBindings = mouseMotion2DBindings; self->gamepadPhysicalMapCount = gamepadPhysicalMapCount; self->gamepadPhysicalMaps = gamepadPhysicalMaps; self->gamepadLogicalMap = gamepadLogicalMap; return true; } void InputMap_serialize(InputMap * self, compat_type(SerializationContext *) serializationContext) { SerializationContext * context = serializationContext; Serialization_enumKeyValue gamepadElementEnumValues[] = GAMEPAD_ELEMENT_ENUM_VALUES; call_virtual(beginStructure, context, "input_map"); call_virtual(writeString, context, "format_type", INPUT_MAP_SERIALIZATION_FORMAT_TYPE); call_virtual(writeUInt16, context, "format_version", INPUT_MAP_SERIALIZATION_FORMAT_VERSION); call_virtual(beginArray, context, "keyboard_bindings"); for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->keyboardBindings[bindingIndex].actionID); call_virtual(writeUInt32, context, "key_code", self->keyboardBindings[bindingIndex].keyCode); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "keyboard_bindings_with_modifiers"); for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingWithModifiersCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->keyboardBindingsWithModifiers[bindingIndex].actionID); call_virtual(writeUInt32, context, "key_code", self->keyboardBindingsWithModifiers[bindingIndex].keyCode); call_virtual(writeUInt8, context, "modifiers", self->keyboardBindingsWithModifiers[bindingIndex].modifierFlags); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "key_modifier_bindings"); for (unsigned int bindingIndex = 0; bindingIndex < self->keyModifierBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->keyModifierBindings[bindingIndex].actionID); call_virtual(writeUInt8, context, "modifier", self->keyModifierBindings[bindingIndex].modifierBit); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "mouse_buttons"); for (unsigned int bindingIndex = 0; bindingIndex < self->mouseButtonBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->mouseButtonBindings[bindingIndex].actionID); call_virtual(writeUInt8, context, "button", self->mouseButtonBindings[bindingIndex].buttonNumber); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "mouse_scroll"); for (unsigned int bindingIndex = 0; bindingIndex < self->mouseScrollBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->mouseScrollBindings[bindingIndex].actionID); call_virtual(writeInt8, context, "direction_x", self->mouseScrollBindings[bindingIndex].directionX); call_virtual(writeInt8, context, "direction_y", self->mouseScrollBindings[bindingIndex].directionY); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "mouse_motion_1d"); for (unsigned int bindingIndex = 0; bindingIndex < self->mouseMotion1DBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->mouseMotion1DBindings[bindingIndex].actionID); call_virtual(writeUInt8, context, "axis", self->mouseMotion1DBindings[bindingIndex].axisNumber); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "mouse_motion_2d"); for (unsigned int bindingIndex = 0; bindingIndex < self->mouseMotion2DBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->mouseMotion2DBindings[bindingIndex].actionID); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "gamepad_maps"); for (unsigned int gamepadPhysicalMapIndex = 0; gamepadPhysicalMapIndex < self->gamepadPhysicalMapCount; gamepadPhysicalMapIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeInt32, context, "vendor_id", self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].vendorID); call_virtual(writeInt32, context, "product_id", self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].productID); call_virtual(beginDictionary, context, "button_bindings"); for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindingCount; bindingIndex++) { call_virtual(writeUInt32, context, self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings[bindingIndex].actionID, self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].buttonActionBindings[bindingIndex].buttonID); } call_virtual(endDictionary, context); call_virtual(beginArray, context, "axis_bindings"); for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings[bindingIndex].actionID); call_virtual(writeUInt32, context, "axis_id", self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings[bindingIndex].axisID); call_virtual(writeFloat, context, "activate_threshold", self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings[bindingIndex].activateThreshold); call_virtual(writeFloat, context, "release_threshold", self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisActionBindings[bindingIndex].releaseThreshold); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "axis_motion_bindings"); for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings[bindingIndex].actionID); call_virtual(writeUInt32, context, "axis_id", self->gamepadPhysicalMaps[gamepadPhysicalMapIndex].axisMotionBindings[bindingIndex].axisID); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "button_actions"); for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.buttonActionBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->gamepadLogicalMap.buttonActionBindings[bindingIndex].actionID); call_virtual(writeEnumeration, context, "element", self->gamepadLogicalMap.buttonActionBindings[bindingIndex].elementID, sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "axis_actions"); for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisActionBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->gamepadLogicalMap.axisActionBindings[bindingIndex].actionID); call_virtual(writeEnumeration, context, "element", self->gamepadLogicalMap.axisActionBindings[bindingIndex].elementID, sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); call_virtual(writeInt8, context, "direction", self->gamepadLogicalMap.axisActionBindings[bindingIndex].direction); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "axis_motions_1d"); for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion1DBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex].actionID); call_virtual(writeEnumeration, context, "element", self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex].elementID, sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(beginArray, context, "axis_motions_2d"); for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion2DBindingCount; bindingIndex++) { call_virtual(beginStructure, context, NULL); call_virtual(writeString, context, "action", self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].actionID); call_virtual(writeEnumeration, context, "element_x", self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDX, sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); call_virtual(writeEnumeration, context, "element_y", self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDY, sizeof_count(gamepadElementEnumValues), gamepadElementEnumValues); call_virtual(endStructure, context); } call_virtual(endArray, context); call_virtual(endStructure, context); } bool InputMap_isKeyBound(InputMap * self, Atom actionID, unsigned int keyCode) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingCount; bindingIndex++) { if ((actionID == NULL || self->keyboardBindings[bindingIndex].actionID == actionID) && self->keyboardBindings[bindingIndex].keyCode == keyCode) { return true; } } return false; } bool InputMap_isKeyWithModifiersBound(InputMap * self, Atom actionID, unsigned int keyCode, unsigned int modifierFlags) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingWithModifiersCount; bindingIndex++) { if ((actionID == NULL || self->keyboardBindingsWithModifiers[bindingIndex].actionID == actionID) && self->keyboardBindingsWithModifiers[bindingIndex].keyCode == keyCode && self->keyboardBindingsWithModifiers[bindingIndex].modifierFlags == modifierFlags) { return true; } } return false; } bool InputMap_isKeyModifierBound(InputMap * self, Atom actionID, unsigned int modifierBit) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyModifierBindingCount; bindingIndex++) { if ((actionID == NULL || self->keyModifierBindings[bindingIndex].actionID == actionID) && self->keyModifierBindings[bindingIndex].modifierBit == modifierBit) { return true; } } return false; } bool InputMap_isMouseButtonBound(InputMap * self, Atom actionID, unsigned int buttonNumber) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseButtonBindingCount; bindingIndex++) { if ((actionID == NULL || self->mouseButtonBindings[bindingIndex].actionID == actionID) && self->mouseButtonBindings[bindingIndex].buttonNumber == buttonNumber) { return true; } } return false; } bool InputMap_isMouseScrollDirectionBound(InputMap * self, Atom actionID, int directionX, int directionY) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseScrollBindingCount; bindingIndex++) { if ((actionID == NULL || self->mouseScrollBindings[bindingIndex].actionID == actionID) && self->mouseScrollBindings[bindingIndex].directionX == directionX && self->mouseScrollBindings[bindingIndex].directionY == directionY) { return true; } } return false; } bool InputMap_isMouseMotion1DBound(InputMap * self, Atom actionID, unsigned int axisNumber) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseMotion1DBindingCount; bindingIndex++) { if ((actionID == NULL || self->mouseMotion1DBindings[bindingIndex].actionID == actionID) && self->mouseMotion1DBindings[bindingIndex].axisNumber == axisNumber) { return true; } } return false; } bool InputMap_isMouseMotion2DBound(InputMap * self, Atom actionID) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseMotion2DBindingCount; bindingIndex++) { if (actionID == NULL || self->mouseMotion2DBindings[bindingIndex].actionID == actionID) { return true; } } return false; } bool InputMap_isPhysicalButtonActionBound(InputMap * self, Atom actionID, int vendorID, int productID, unsigned int buttonID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount; bindingIndex++) { if ((actionID == NULL || self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex].actionID == actionID) && self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex].buttonID == buttonID) { return true; } } } } return false; } bool InputMap_isPhysicalAxisActionBound(InputMap * self, Atom actionID, int vendorID, int productID, unsigned int axisID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount; bindingIndex++) { if ((actionID == NULL || self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].actionID == actionID) && self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].axisID == axisID) { return true; } } } } return false; } bool InputMap_isPhysicalAxisMotionBound(InputMap * self, Atom actionID, int vendorID, int productID, unsigned int axisID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount; bindingIndex++) { if ((actionID == NULL || self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex].actionID == actionID) && self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex].axisID == axisID) { return true; } } } } return false; } bool InputMap_isLogicalButtonActionBound(InputMap * self, Atom actionID, GamepadElement elementID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.buttonActionBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.buttonActionBindings[bindingIndex].actionID == actionID && self->gamepadLogicalMap.buttonActionBindings[bindingIndex].elementID == elementID) { return true; } } return false; } bool InputMap_isLogicalAxisActionBound(InputMap * self, Atom actionID, GamepadElement elementID, int direction) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisActionBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisActionBindings[bindingIndex].actionID == actionID && self->gamepadLogicalMap.axisActionBindings[bindingIndex].elementID == elementID && self->gamepadLogicalMap.axisActionBindings[bindingIndex].direction == direction) { return true; } } return false; } bool InputMap_isLogicalAxisMotion1DBound(InputMap * self, Atom actionID, GamepadElement elementID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion1DBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex].actionID == actionID && self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex].elementID == elementID) { return true; } } return false; } bool InputMap_isLogicalAxisMotion2DBound(InputMap * self, Atom actionID, GamepadElement elementIDX, GamepadElement elementIDY) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion2DBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].actionID == actionID && self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDX == elementIDX && self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDY == elementIDY) { return true; } } return false; } void InputMap_bindKey(InputMap * self, Atom actionID, unsigned int keyCode) { if (!InputMap_isKeyBound(self, actionID, keyCode)) { self->keyboardBindings = realloc(self->keyboardBindings, (self->keyboardBindingCount + 1) * sizeof(*self->keyboardBindings)); self->keyboardBindings[self->keyboardBindingCount].actionID = actionID; self->keyboardBindings[self->keyboardBindingCount].keyCode = keyCode; self->keyboardBindingCount++; } } void InputMap_bindKeyWithModifiers(InputMap * self, Atom actionID, unsigned int keyCode, unsigned int modifierFlags) { if (!InputMap_isKeyWithModifiersBound(self, actionID, keyCode, modifierFlags)) { self->keyboardBindingsWithModifiers = realloc(self->keyboardBindingsWithModifiers, (self->keyboardBindingWithModifiersCount + 1) * sizeof(*self->keyboardBindingsWithModifiers)); self->keyboardBindingsWithModifiers[self->keyboardBindingWithModifiersCount].actionID = actionID; self->keyboardBindingsWithModifiers[self->keyboardBindingWithModifiersCount].keyCode = keyCode; self->keyboardBindingsWithModifiers[self->keyboardBindingWithModifiersCount].modifierFlags = modifierFlags; self->keyboardBindingWithModifiersCount++; } } void InputMap_bindKeyModifier(InputMap * self, Atom actionID, unsigned int modifierBit) { if (!InputMap_isKeyModifierBound(self, actionID, modifierBit)) { self->keyModifierBindings = realloc(self->keyModifierBindings, (self->keyModifierBindingCount + 1) * sizeof(*self->keyModifierBindings)); self->keyModifierBindings[self->keyModifierBindingCount].actionID = actionID; self->keyModifierBindings[self->keyModifierBindingCount].modifierBit = modifierBit; self->keyModifierBindingCount++; } } void InputMap_bindMouseButton(InputMap * self, Atom actionID, unsigned int buttonNumber) { if (!InputMap_isMouseButtonBound(self, actionID, buttonNumber)) { self->mouseButtonBindings = realloc(self->mouseButtonBindings, (self->mouseButtonBindingCount + 1) * sizeof(*self->mouseButtonBindings)); self->mouseButtonBindings[self->mouseButtonBindingCount].actionID = actionID; self->mouseButtonBindings[self->mouseButtonBindingCount].buttonNumber = buttonNumber; self->mouseButtonBindingCount++; } } void InputMap_bindMouseScrollDirection(InputMap * self, Atom actionID, int directionX, int directionY) { if (!InputMap_isMouseScrollDirectionBound(self, actionID, directionX, directionY)) { self->mouseScrollBindings = realloc(self->mouseScrollBindings, (self->mouseScrollBindingCount + 1) * sizeof(*self->mouseScrollBindings)); self->mouseScrollBindings[self->mouseScrollBindingCount].actionID = actionID; self->mouseScrollBindings[self->mouseScrollBindingCount].directionX = directionX; self->mouseScrollBindings[self->mouseScrollBindingCount].directionY = directionY; self->mouseScrollBindingCount++; } } void InputMap_bindMouseMotion1D(InputMap * self, Atom actionID, unsigned int axisNumber) { if (!InputMap_isMouseMotion1DBound(self, actionID, axisNumber)) { self->mouseMotion1DBindings = realloc(self->mouseMotion1DBindings, (self->mouseMotion1DBindingCount + 1) * sizeof(*self->mouseMotion1DBindings)); self->mouseMotion1DBindings[self->mouseMotion1DBindingCount].actionID = actionID; self->mouseMotion1DBindings[self->mouseMotion1DBindingCount].axisNumber = axisNumber; self->mouseMotion1DBindingCount++; } } void InputMap_bindMouseMotion2D(InputMap * self, Atom actionID) { if (!InputMap_isMouseMotion2DBound(self, actionID)) { self->mouseMotion2DBindings = realloc(self->mouseMotion2DBindings, (self->mouseMotion2DBindingCount + 1) * sizeof(*self->mouseMotion2DBindings)); self->mouseMotion2DBindings[self->mouseMotion2DBindingCount].actionID = actionID; self->mouseMotion2DBindingCount++; } } static struct InputMap_gamepadPhysicalMap * addGamepadPhysicalMap(InputMap * self, int vendorID, int productID) { self->gamepadPhysicalMaps = realloc(self->gamepadPhysicalMaps, (self->gamepadPhysicalMapCount + 1) * sizeof(*self->gamepadPhysicalMaps)); self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].vendorID = vendorID; self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].productID = productID; self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].buttonActionBindingCount = 0; self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].buttonActionBindings = NULL; self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].axisActionBindingCount = 0; self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].axisActionBindings = NULL; self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].axisMotionBindingCount = 0; self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].axisMotionBindings = NULL; return &self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount++]; } void InputMap_bindPhysicalButtonAction(InputMap * self, Atom actionID, int vendorID, int productID, unsigned int buttonID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex].actionID == actionID && self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex].buttonID == buttonID) { return; } } self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings = realloc(self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings, (self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount + 1) * sizeof(*self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings)); self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount].actionID = actionID; self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount].buttonID = buttonID; self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount++; return; } } struct InputMap_gamepadPhysicalMap * gamepadPhysicalMap = addGamepadPhysicalMap(self, vendorID, productID); gamepadPhysicalMap->buttonActionBindingCount = 1; gamepadPhysicalMap->buttonActionBindings = malloc(sizeof(*self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].buttonActionBindings)); gamepadPhysicalMap->buttonActionBindings[0].actionID = actionID; gamepadPhysicalMap->buttonActionBindings[0].buttonID = buttonID; } void InputMap_bindPhysicalAxisAction(InputMap * self, Atom actionID, int vendorID, int productID, unsigned int axisID, float activateThreshold, float releaseThreshold) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].actionID == actionID && self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].axisID == axisID) { self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].activateThreshold = activateThreshold; self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].releaseThreshold = releaseThreshold; return; } } self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings = realloc(self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings, (self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount + 1) * sizeof(*self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings)); self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount].actionID = actionID; self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount].axisID = axisID; self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount].activateThreshold = activateThreshold; self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount].releaseThreshold = releaseThreshold; self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount++; return; } } struct InputMap_gamepadPhysicalMap * gamepadPhysicalMap = addGamepadPhysicalMap(self, vendorID, productID); gamepadPhysicalMap->axisActionBindingCount = 1; gamepadPhysicalMap->axisActionBindings = malloc(sizeof(*self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].axisActionBindings)); gamepadPhysicalMap->axisActionBindings[0].actionID = actionID; gamepadPhysicalMap->axisActionBindings[0].axisID = axisID; gamepadPhysicalMap->axisActionBindings[0].activateThreshold = activateThreshold; gamepadPhysicalMap->axisActionBindings[0].releaseThreshold = releaseThreshold; } void InputMap_bindPhysicalAxisMotion(InputMap * self, Atom actionID, int vendorID, int productID, unsigned int axisID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex].actionID == actionID && self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex].axisID == axisID) { return; } } self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings = realloc(self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings, (self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount + 1) * sizeof(*self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings)); self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount].actionID = actionID; self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount].axisID = axisID; self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount++; return; } } struct InputMap_gamepadPhysicalMap * gamepadPhysicalMap = addGamepadPhysicalMap(self, vendorID, productID); gamepadPhysicalMap->axisMotionBindingCount = 1; gamepadPhysicalMap->axisMotionBindings = malloc(sizeof(*self->gamepadPhysicalMaps[self->gamepadPhysicalMapCount].axisMotionBindings)); gamepadPhysicalMap->axisMotionBindings[0].actionID = actionID; gamepadPhysicalMap->axisMotionBindings[0].axisID = axisID; } void InputMap_bindLogicalButtonAction(InputMap * self, Atom actionID, GamepadElement elementID) { if (InputMap_isLogicalButtonActionBound(self, actionID, elementID)) { return; } self->gamepadLogicalMap.buttonActionBindings = realloc(self->gamepadLogicalMap.buttonActionBindings, (self->gamepadLogicalMap.buttonActionBindingCount + 1) * sizeof(*self->gamepadLogicalMap.buttonActionBindings)); self->gamepadLogicalMap.buttonActionBindings[self->gamepadLogicalMap.buttonActionBindingCount].actionID = actionID; self->gamepadLogicalMap.buttonActionBindings[self->gamepadLogicalMap.buttonActionBindingCount].elementID = elementID; self->gamepadLogicalMap.buttonActionBindingCount++; } void InputMap_bindLogicalAxisAction(InputMap * self, Atom actionID, GamepadElement elementID, int direction) { if (InputMap_isLogicalAxisActionBound(self, actionID, elementID, direction)) { return; } self->gamepadLogicalMap.axisActionBindings = realloc(self->gamepadLogicalMap.axisActionBindings, (self->gamepadLogicalMap.axisActionBindingCount + 1) * sizeof(*self->gamepadLogicalMap.axisActionBindings)); self->gamepadLogicalMap.axisActionBindings[self->gamepadLogicalMap.axisActionBindingCount].actionID = actionID; self->gamepadLogicalMap.axisActionBindings[self->gamepadLogicalMap.axisActionBindingCount].elementID = elementID; self->gamepadLogicalMap.axisActionBindings[self->gamepadLogicalMap.axisActionBindingCount].direction = direction; self->gamepadLogicalMap.axisActionBindingCount++; } void InputMap_bindLogicalAxisMotion1D(InputMap * self, Atom actionID, GamepadElement elementID) { if (InputMap_isLogicalAxisMotion1DBound(self, actionID, elementID)) { return; } self->gamepadLogicalMap.axisMotion1DBindings = realloc(self->gamepadLogicalMap.axisMotion1DBindings, (self->gamepadLogicalMap.axisMotion1DBindingCount + 1) * sizeof(*self->gamepadLogicalMap.axisMotion1DBindings)); self->gamepadLogicalMap.axisMotion1DBindings[self->gamepadLogicalMap.axisMotion1DBindingCount].actionID = actionID; self->gamepadLogicalMap.axisMotion1DBindings[self->gamepadLogicalMap.axisMotion1DBindingCount].elementID = elementID; self->gamepadLogicalMap.axisMotion1DBindingCount++; } void InputMap_bindLogicalAxisMotion2D(InputMap * self, Atom actionID, GamepadElement elementIDX, GamepadElement elementIDY) { if (InputMap_isLogicalAxisMotion2DBound(self, actionID, elementIDX, elementIDY)) { return; } self->gamepadLogicalMap.axisMotion2DBindings = realloc(self->gamepadLogicalMap.axisMotion2DBindings, (self->gamepadLogicalMap.axisMotion2DBindingCount + 1) * sizeof(*self->gamepadLogicalMap.axisMotion2DBindings)); self->gamepadLogicalMap.axisMotion2DBindings[self->gamepadLogicalMap.axisMotion2DBindingCount].actionID = actionID; self->gamepadLogicalMap.axisMotion2DBindings[self->gamepadLogicalMap.axisMotion2DBindingCount].elementIDX = elementIDX; self->gamepadLogicalMap.axisMotion2DBindings[self->gamepadLogicalMap.axisMotion2DBindingCount].elementIDY = elementIDY; self->gamepadLogicalMap.axisMotion2DBindingCount++; } static void removeKeyBinding(InputMap * self, unsigned int bindingIndex) { self->keyboardBindingCount--; for (; bindingIndex < self->keyboardBindingCount; bindingIndex++) { self->keyboardBindings[bindingIndex] = self->keyboardBindings[bindingIndex + 1]; } } static void removeKeyBindingWithModifiers(InputMap * self, unsigned int bindingIndex) { self->keyboardBindingCount--; for (; bindingIndex < self->keyboardBindingWithModifiersCount; bindingIndex++) { self->keyboardBindingsWithModifiers[bindingIndex] = self->keyboardBindingsWithModifiers[bindingIndex + 1]; } } static void removeKeyModifierBinding(InputMap * self, unsigned int bindingIndex) { self->keyModifierBindingCount--; for (; bindingIndex < self->keyModifierBindingCount; bindingIndex++) { self->keyModifierBindings[bindingIndex] = self->keyModifierBindings[bindingIndex + 1]; } } static void removeMouseButtonBinding(InputMap * self, unsigned int bindingIndex) { self->mouseButtonBindingCount--; for (; bindingIndex < self->mouseButtonBindingCount; bindingIndex++) { self->mouseButtonBindings[bindingIndex] = self->mouseButtonBindings[bindingIndex + 1]; } } static void removeMouseScrollBinding(InputMap * self, unsigned int bindingIndex) { self->mouseScrollBindingCount--; for (; bindingIndex < self->mouseScrollBindingCount; bindingIndex++) { self->mouseScrollBindings[bindingIndex] = self->mouseScrollBindings[bindingIndex + 1]; } } static void removeMouseMotion1DBinding(InputMap * self, unsigned int bindingIndex) { self->mouseMotion1DBindingCount--; for (; bindingIndex < self->mouseMotion1DBindingCount; bindingIndex++) { self->mouseMotion1DBindings[bindingIndex] = self->mouseMotion1DBindings[bindingIndex + 1]; } } static void removeMouseMotion2DBinding(InputMap * self, unsigned int bindingIndex) { self->mouseMotion2DBindingCount--; for (; bindingIndex < self->mouseMotion2DBindingCount; bindingIndex++) { self->mouseMotion2DBindings[bindingIndex] = self->mouseMotion2DBindings[bindingIndex + 1]; } } static void removePhysicalButtonActionBinding(InputMap * self, unsigned int gamepadIndex, unsigned int bindingIndex) { self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount--; for (; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount; bindingIndex++) { self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex] = self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex + 1]; } } static void removePhysicalAxisActionBinding(InputMap * self, unsigned int gamepadIndex, unsigned int bindingIndex) { self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount--; for (; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount; bindingIndex++) { self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex] = self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex + 1]; } } static void removePhysicalAxisMotionBinding(InputMap * self, unsigned int gamepadIndex, unsigned int bindingIndex) { self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount--; for (; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount; bindingIndex++) { self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex] = self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex + 1]; } } static void removeGamepadPhysicalMapIfEmpty(InputMap * self, unsigned int * ioGamepadIndex) { unsigned int gamepadIndex = *ioGamepadIndex; if (self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount == 0 && self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount == 0 && self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount == 0) { free(self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings); free(self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings); free(self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings); self->gamepadPhysicalMapCount--; for (; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { self->gamepadPhysicalMaps[gamepadIndex] = self->gamepadPhysicalMaps[gamepadIndex + 1]; } *ioGamepadIndex -= 1; } } static void removeLogicalButtonActionBinding(InputMap * self, unsigned int bindingIndex) { self->gamepadLogicalMap.buttonActionBindingCount--; for (; bindingIndex < self->gamepadLogicalMap.buttonActionBindingCount; bindingIndex++) { self->gamepadLogicalMap.buttonActionBindings[bindingIndex] = self->gamepadLogicalMap.buttonActionBindings[bindingIndex + 1]; } } static void removeLogicalAxisActionBinding(InputMap * self, unsigned int bindingIndex) { self->gamepadLogicalMap.axisActionBindingCount--; for (; bindingIndex < self->gamepadLogicalMap.axisActionBindingCount; bindingIndex++) { self->gamepadLogicalMap.axisActionBindings[bindingIndex] = self->gamepadLogicalMap.axisActionBindings[bindingIndex + 1]; } } static void removeLogicalAxisMotion1DBinding(InputMap * self, unsigned int bindingIndex) { self->gamepadLogicalMap.axisMotion1DBindingCount--; for (; bindingIndex < self->gamepadLogicalMap.axisMotion1DBindingCount; bindingIndex++) { self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex] = self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex + 1]; } } static void removeLogicalAxisMotion2DBinding(InputMap * self, unsigned int bindingIndex) { self->gamepadLogicalMap.axisMotion2DBindingCount--; for (; bindingIndex < self->gamepadLogicalMap.axisMotion2DBindingCount; bindingIndex++) { self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex] = self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex + 1]; } } void InputMap_unbindKey(InputMap * self, Atom actionID, unsigned int keyCode) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingCount; bindingIndex++) { if (self->keyboardBindings[bindingIndex].actionID == actionID && self->keyboardBindings[bindingIndex].keyCode == keyCode) { removeKeyBinding(self, bindingIndex); break; } } } void InputMap_unbindKeyWithModifiers(InputMap * self, Atom actionID, unsigned int keyCode, unsigned int modifierFlags) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingWithModifiersCount; bindingIndex++) { if (self->keyboardBindingsWithModifiers[bindingIndex].actionID == actionID && self->keyboardBindingsWithModifiers[bindingIndex].keyCode == keyCode && self->keyboardBindingsWithModifiers[bindingIndex].modifierFlags == modifierFlags) { removeKeyBindingWithModifiers(self, bindingIndex); break; } } } void InputMap_unbindKeyModifier(InputMap * self, Atom actionID, unsigned int modifierBit) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyModifierBindingCount; bindingIndex++) { if (self->keyModifierBindings[bindingIndex].actionID == actionID && self->keyModifierBindings[bindingIndex].modifierBit == modifierBit) { removeKeyModifierBinding(self, bindingIndex); break; } } } void InputMap_unbindMouseButton(InputMap * self, Atom actionID, unsigned int buttonNumber) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseButtonBindingCount; bindingIndex++) { if (self->mouseButtonBindings[bindingIndex].actionID == actionID && self->mouseButtonBindings[bindingIndex].buttonNumber == buttonNumber) { removeMouseButtonBinding(self, bindingIndex); break; } } } void InputMap_unbindMouseScrollDirection(InputMap * self, Atom actionID, int directionX, int directionY) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseScrollBindingCount; bindingIndex++) { if (self->mouseScrollBindings[bindingIndex].actionID == actionID && self->mouseScrollBindings[bindingIndex].directionX == directionX && self->mouseScrollBindings[bindingIndex].directionY) { removeMouseScrollBinding(self, bindingIndex); break; } } } void InputMap_unbindMouseMotion1D(InputMap * self, Atom actionID, unsigned int axisNumber) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseMotion1DBindingCount; bindingIndex++) { if (self->mouseMotion1DBindings[bindingIndex].actionID == actionID && self->mouseMotion1DBindings[bindingIndex].axisNumber == axisNumber) { removeMouseMotion1DBinding(self, bindingIndex); break; } } } void InputMap_unbindMouseMotion2D(InputMap * self, Atom actionID) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseMotion2DBindingCount; bindingIndex++) { if (self->mouseMotion2DBindings[bindingIndex].actionID == actionID) { removeMouseMotion2DBinding(self, bindingIndex); break; } } } void InputMap_unbindPhysicalButtonAction(InputMap * self, Atom actionID, int vendorID, int productID, unsigned int buttonID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex].actionID == actionID && self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex].buttonID == buttonID) { removePhysicalButtonActionBinding(self, gamepadIndex, bindingIndex); removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); return; } } return; } } } void InputMap_unbindPhysicalAxisAction(InputMap * self, Atom actionID, int vendorID, int productID, unsigned int axisID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].actionID == actionID && self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].axisID == axisID) { removePhysicalAxisActionBinding(self, gamepadIndex, bindingIndex); removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); return; } } return; } } } void InputMap_unbindPhysicalAxisMotion(InputMap * self, Atom actionID, int vendorID, int productID, unsigned int axisID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex].actionID == actionID && self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex].axisID == axisID) { removePhysicalAxisMotionBinding(self, gamepadIndex, bindingIndex); removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); return; } } return; } } } void InputMap_unbindLogicalButtonAction(InputMap * self, Atom actionID, GamepadElement elementID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.buttonActionBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.buttonActionBindings[bindingIndex].actionID == actionID && self->gamepadLogicalMap.buttonActionBindings[bindingIndex].elementID == elementID) { removeLogicalButtonActionBinding(self, bindingIndex); return; } } } void InputMap_unbindLogicalAxisAction(InputMap * self, Atom actionID, GamepadElement elementID, int direction) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisActionBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisActionBindings[bindingIndex].actionID == actionID && self->gamepadLogicalMap.axisActionBindings[bindingIndex].elementID == elementID && self->gamepadLogicalMap.axisActionBindings[bindingIndex].direction == direction) { removeLogicalAxisActionBinding(self, bindingIndex); return; } } } void InputMap_unbindLogicalAxisMotion1D(InputMap * self, Atom actionID, GamepadElement elementID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion1DBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex].actionID == actionID && self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex].elementID == elementID) { removeLogicalAxisMotion1DBinding(self, bindingIndex); return; } } } void InputMap_unbindLogicalAxisMotion2D(InputMap * self, Atom actionID, GamepadElement elementIDX, GamepadElement elementIDY) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion2DBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].actionID == actionID && self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDX == elementIDX && self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDY == elementIDY) { removeLogicalAxisMotion2DBinding(self, bindingIndex); return; } } } void InputMap_unbindAllKeysForAction(InputMap * self, Atom actionID) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingCount; bindingIndex++) { if (self->keyboardBindings[bindingIndex].actionID == actionID) { removeKeyBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllKeysWithModifiersForAction(InputMap * self, Atom actionID) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingWithModifiersCount; bindingIndex++) { if (self->keyboardBindingsWithModifiers[bindingIndex].actionID == actionID) { removeKeyBindingWithModifiers(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllKeyModifiersForAction(InputMap * self, Atom actionID) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyModifierBindingCount; bindingIndex++) { if (self->keyModifierBindings[bindingIndex].actionID == actionID) { removeKeyModifierBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllMouseButtonsForAction(InputMap * self, Atom actionID) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseButtonBindingCount; bindingIndex++) { if (self->mouseButtonBindings[bindingIndex].actionID == actionID) { removeMouseButtonBinding(self, bindingIndex); bindingIndex--; } } for (unsigned int bindingIndex = 0; bindingIndex < self->mouseScrollBindingCount; bindingIndex++) { if (self->mouseScrollBindings[bindingIndex].actionID == actionID) { removeMouseScrollBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllMouseMotionForAction(InputMap * self, Atom actionID) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseMotion1DBindingCount; bindingIndex++) { if (self->mouseMotion1DBindings[bindingIndex].actionID == actionID) { removeMouseMotion1DBinding(self, bindingIndex); bindingIndex--; } } for (unsigned int bindingIndex = 0; bindingIndex < self->mouseMotion2DBindingCount; bindingIndex++) { if (self->mouseMotion2DBindings[bindingIndex].actionID == actionID) { removeMouseMotion2DBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllPhysicalButtonsForAction(InputMap * self, Atom actionID) { for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex].actionID == actionID) { removePhysicalButtonActionBinding(self, gamepadIndex, bindingIndex); bindingIndex--; } } removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); } } void InputMap_unbindAllPhysicalAxesForAction(InputMap * self, Atom actionID) { for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].actionID == actionID) { removePhysicalAxisActionBinding(self, gamepadIndex, bindingIndex); bindingIndex--; } } for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex].actionID == actionID) { removePhysicalAxisMotionBinding(self, gamepadIndex, bindingIndex); bindingIndex--; } } removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); } } void InputMap_unbindAllLogicalButtonsForAction(InputMap * self, Atom actionID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.buttonActionBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.buttonActionBindings[bindingIndex].actionID == actionID) { removeLogicalButtonActionBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllLogicalAxesForAction(InputMap * self, Atom actionID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisActionBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisActionBindings[bindingIndex].actionID == actionID) { removeLogicalAxisActionBinding(self, bindingIndex); bindingIndex--; } } for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion1DBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex].actionID == actionID) { removeLogicalAxisMotion1DBinding(self, bindingIndex); bindingIndex--; } } for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion2DBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].actionID == actionID) { removeLogicalAxisMotion2DBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllPhysicalButtonsOnDeviceForAction(InputMap * self, int vendorID, int productID, Atom actionID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex].actionID == actionID) { removePhysicalButtonActionBinding(self, gamepadIndex, bindingIndex); bindingIndex--; } } removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); return; } } } void InputMap_unbindAllPhysicalAxesOnDeviceForAction(InputMap * self, int vendorID, int productID, Atom actionID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].actionID == actionID) { removePhysicalAxisActionBinding(self, gamepadIndex, bindingIndex); bindingIndex--; } } for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex].actionID == actionID) { removePhysicalAxisMotionBinding(self, gamepadIndex, bindingIndex); bindingIndex--; } } removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); return; } } } void InputMap_unbindAllActionsForKey(InputMap * self, unsigned int keyCode) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingCount; bindingIndex++) { if (self->keyboardBindings[bindingIndex].keyCode == keyCode) { removeKeyBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllActionsForKeyWithModifiers(InputMap * self, unsigned int keyCode, unsigned int modifierFlags) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyboardBindingWithModifiersCount; bindingIndex++) { if (self->keyboardBindingsWithModifiers[bindingIndex].keyCode == keyCode && self->keyboardBindingsWithModifiers[bindingIndex].modifierFlags == modifierFlags) { removeKeyBindingWithModifiers(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllActionsForKeyModifier(InputMap * self, unsigned int modifierBit) { for (unsigned int bindingIndex = 0; bindingIndex < self->keyModifierBindingCount; bindingIndex++) { if (self->keyModifierBindings[bindingIndex].modifierBit == modifierBit) { removeKeyModifierBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllActionsForMouseButton(InputMap * self, unsigned int buttonNumber) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseButtonBindingCount; bindingIndex++) { if (self->mouseButtonBindings[bindingIndex].buttonNumber == buttonNumber) { removeMouseButtonBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllActionsForMouseScrollDirection(InputMap * self, int directionX, int directionY) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseScrollBindingCount; bindingIndex++) { if (self->mouseScrollBindings[bindingIndex].directionX == directionX && self->mouseScrollBindings[bindingIndex].directionY == directionY) { removeMouseScrollBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllActionsForMouseMotion1D(InputMap * self, unsigned int axisNumber) { for (unsigned int bindingIndex = 0; bindingIndex < self->mouseMotion1DBindingCount; bindingIndex++) { if (self->mouseMotion1DBindings[bindingIndex].axisNumber == axisNumber) { removeMouseMotion1DBinding(self, bindingIndex); bindingIndex--; } } } void InputMap_unbindAllActionsForMouseMotion2D(InputMap * self) { self->mouseMotion2DBindingCount = 0; free(self->mouseMotion2DBindings); self->mouseMotion2DBindings = NULL; } void InputMap_unbindAllActionsForPhysicalButton(InputMap * self, int vendorID, int productID, unsigned int buttonID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindings[bindingIndex].buttonID == buttonID) { removePhysicalButtonActionBinding(self, gamepadIndex, bindingIndex); bindingIndex--; } } removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); return; } } } void InputMap_unbindAllActionsForPhysicalAxis(InputMap * self, int vendorID, int productID, unsigned int axisID, bool positive) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].axisID == axisID && (self->gamepadPhysicalMaps[gamepadIndex].axisActionBindings[bindingIndex].activateThreshold > 0.0f) == positive) { removePhysicalAxisActionBinding(self, gamepadIndex, bindingIndex); bindingIndex--; } } removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); return; } } } void InputMap_unbindAllMotionsForPhysicalAxis(InputMap * self, int vendorID, int productID, unsigned int axisID) { InputMap_resolveGamepadAlias(self, &vendorID, &productID); for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].vendorID == vendorID && self->gamepadPhysicalMaps[gamepadIndex].productID == productID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount; bindingIndex++) { if (self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindings[bindingIndex].axisID == axisID) { removePhysicalAxisMotionBinding(self, gamepadIndex, bindingIndex); bindingIndex--; } } removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); return; } } } void InputMap_unbindAllActionsForLogicalButton(InputMap * self, GamepadElement elementID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.buttonActionBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.buttonActionBindings[bindingIndex].elementID == elementID) { removeLogicalButtonActionBinding(self, bindingIndex); } } } void InputMap_unbindAllActionsForLogicalAxis(InputMap * self, GamepadElement elementID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisActionBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisActionBindings[bindingIndex].elementID == elementID) { removeLogicalAxisActionBinding(self, bindingIndex); } } } void InputMap_unbindAllMotionsForLogicalAxis(InputMap * self, GamepadElement elementID) { for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion1DBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisMotion1DBindings[bindingIndex].elementID == elementID) { removeLogicalAxisMotion1DBinding(self, bindingIndex); } } for (unsigned int bindingIndex = 0; bindingIndex < self->gamepadLogicalMap.axisMotion2DBindingCount; bindingIndex++) { if (self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDX == elementID || self->gamepadLogicalMap.axisMotion2DBindings[bindingIndex].elementIDY == elementID) { removeLogicalAxisMotion2DBinding(self, bindingIndex); } } } void InputMap_unbindAllKeys(InputMap * self) { self->keyboardBindingCount = 0; } void InputMap_unbindAllKeysWithModifiers(InputMap * self) { self->keyboardBindingWithModifiersCount = 0; } void InputMap_unbindAllKeyModifiers(InputMap * self) { self->keyModifierBindingCount = 0; } void InputMap_unbindAllMouseButtons(InputMap * self) { self->mouseButtonBindingCount = 0; self->mouseScrollBindingCount = 0; } void InputMap_unbindAllMouseMotion(InputMap * self) { self->mouseMotion1DBindingCount = 0; self->mouseMotion2DBindingCount = 0; } void InputMap_unbindAllPhysicalButtons(InputMap * self) { for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { self->gamepadPhysicalMaps[gamepadIndex].buttonActionBindingCount = 0; removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); } } void InputMap_unbindAllPhysicalAxes(InputMap * self) { for (unsigned int gamepadIndex = 0; gamepadIndex < self->gamepadPhysicalMapCount; gamepadIndex++) { self->gamepadPhysicalMaps[gamepadIndex].axisActionBindingCount = 0; self->gamepadPhysicalMaps[gamepadIndex].axisMotionBindingCount = 0; removeGamepadPhysicalMapIfEmpty(self, &gamepadIndex); } } void InputMap_unbindAllLogicalButtons(InputMap * self) { self->gamepadLogicalMap.buttonActionBindingCount = 0; } void InputMap_unbindAllLogicalAxes(InputMap * self) { self->gamepadLogicalMap.axisActionBindingCount = 0; self->gamepadLogicalMap.axisMotion1DBindingCount = 0; self->gamepadLogicalMap.axisMotion2DBindingCount = 0; } void InputMap_addGamepadAlias(InputMap * self, int vendorID1, int productID1, int vendorID2, int productID2) { self->gamepadAliases = realloc(self->gamepadAliases, (self->gamepadAliasCount + 1) * sizeof(*self->gamepadAliases)); self->gamepadAliases[self->gamepadAliasCount].vendorID1 = vendorID1; self->gamepadAliases[self->gamepadAliasCount].productID1 = productID1; self->gamepadAliases[self->gamepadAliasCount].vendorID2 = vendorID2; self->gamepadAliases[self->gamepadAliasCount].productID2 = productID2; self->gamepadAliasCount++; } static bool resolveGamepadAliasInternal(InputMap * self, int * ioVendorID, int * ioProductID) { for (unsigned int aliasIndex = 0; aliasIndex < self->gamepadAliasCount; aliasIndex++) { if (self->gamepadAliases[aliasIndex].vendorID2 == *ioVendorID && self->gamepadAliases[aliasIndex].productID2 == *ioProductID) { *ioVendorID = self->gamepadAliases[aliasIndex].vendorID1; *ioProductID = self->gamepadAliases[aliasIndex].productID1; return true; } } return false; } void InputMap_resolveGamepadAlias(InputMap * self, int * ioVendorID, int * ioProductID) { while (resolveGamepadAliasInternal(self, ioVendorID, ioProductID)); } #define enumerateBindingsImplementation(count, bindings_field, suffix) \ for (unsigned int bindingIndex = 0; bindingIndex < self->count; bindingIndex++) { \ if (self->bindings_field[bindingIndex].actionID == actionID) { \ InputMap_bindingGeneric binding = {.type = InputMap_bindingType_##suffix, .binding = {.suffix = self->bindings_field[bindingIndex]}}; \ if (!callback(self, binding, callbackContext)) { \ return; \ } \ } \ } void InputMap_enumerateBindingsForAction(InputMap * self, Atom actionID, InputMap_enumerateBindingCallback callback, void * callbackContext) { enumerateBindingsImplementation(keyboardBindingCount, keyboardBindings, key); enumerateBindingsImplementation(keyboardBindingWithModifiersCount, keyboardBindingsWithModifiers, keyWithModifiers); enumerateBindingsImplementation(keyModifierBindingCount, keyModifierBindings, keyModifier); enumerateBindingsImplementation(mouseButtonBindingCount, mouseButtonBindings, mouseButton); enumerateBindingsImplementation(mouseScrollBindingCount, mouseScrollBindings, mouseScrollWheel); enumerateBindingsImplementation(mouseMotion1DBindingCount, mouseMotion1DBindings, mouseMotion1D); enumerateBindingsImplementation(mouseMotion2DBindingCount, mouseMotion2DBindings, mouseMotion2D); enumerateBindingsImplementation(gamepadLogicalMap.buttonActionBindingCount, gamepadLogicalMap.buttonActionBindings, gamepadButton); enumerateBindingsImplementation(gamepadLogicalMap.axisActionBindingCount, gamepadLogicalMap.axisActionBindings, gamepadAxisAction); enumerateBindingsImplementation(gamepadLogicalMap.axisMotion1DBindingCount, gamepadLogicalMap.axisMotion1DBindings, gamepadAxisMotion1D); enumerateBindingsImplementation(gamepadLogicalMap.axisMotion2DBindingCount, gamepadLogicalMap.axisMotion2DBindings, gamepadAxisMotion2D); }