UNPKG

joymap

Version:

A Gamepad API wrapper and mapping tool.

213 lines (173 loc) 5.44 kB
import memoize from 'fast-memoize'; import { assignIn, mapValues, omit, forEach } from 'lodash/fp'; import { buttonMap, stickMap } from '../common/utils'; import createBaseModule from '../baseModule/base'; import { StickResult, ButtonResult } from '../types'; // the following definition allows for the circular Mapper type // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface QueryModule extends ReturnType<typeof createQueryModule> {} export type MapperResult = any; export type Mapper = (module: QueryModule) => MapperResult; export const emptyMapper: MapperResult = null; export const emptyStick: StickResult = { type: 'stick', value: [0, 0], pressed: false, justChanged: false, inverts: [false, false], }; export const emptyButton: ButtonResult = { type: 'button', value: 0, pressed: false, justChanged: false, }; export default function createQueryModule(params = {}) { const { state, module: baseModule } = createBaseModule(params); let mappers: Record<string, Mapper> = {}; const buttonMapMemoized = memoize(buttonMap); const stickMapMemoized = memoize(stickMap); const module = assignIn(baseModule, { getButton: (inputName: string) => { if (!module.isConnected()) { return emptyButton; } return buttonMapMemoized( state.pad, state.prevPad, state.buttons[inputName], state.threshold, state.clampThreshold, ); }, getButtons: (...inputNames: string[]) => { if (!module.isConnected()) { const result: Record<string, ButtonResult> = {}; forEach((mapperName) => { result[mapperName] = emptyButton; }, inputNames); return result; } const result: Record<string, ButtonResult> = {}; forEach((inputName) => { result[inputName] = buttonMapMemoized( state.pad, state.prevPad, state.buttons[inputName], state.threshold, state.clampThreshold, ); }, inputNames); return result; }, getAllButtons: (): Record<string, ButtonResult> => { if (!module.isConnected()) { return mapValues(state.buttons, () => emptyButton); } return mapValues( (button) => buttonMapMemoized( state.pad, state.prevPad, button, state.threshold, state.clampThreshold, ), state.buttons, ); }, getStick: (inputName: string) => { if (!module.isConnected()) { return emptyStick; } const { indexes, inverts } = state.sticks[inputName]; return stickMapMemoized( state.pad, state.prevPad, indexes, inverts, state.threshold, state.clampThreshold, ); }, getSticks: (...inputNames: string[]) => { if (!module.isConnected()) { const result: Record<string, StickResult> = {}; forEach((mapperName) => { result[mapperName] = emptyStick; }, inputNames); return result; } const result: Record<string, StickResult> = {}; forEach((inputName) => { const { indexes, inverts } = state.sticks[inputName]; result[inputName] = stickMapMemoized( state.pad, state.prevPad, indexes, inverts, state.threshold, state.clampThreshold, ); }, inputNames); return result; }, getAllSticks: (): Record<string, StickResult> => { if (!module.isConnected()) { return mapValues(state.sticks, () => emptyStick); } return mapValues((stick) => { const { indexes, inverts } = stick; return stickMapMemoized( state.pad, state.prevPad, indexes, inverts, state.threshold, state.clampThreshold, ); }, state.sticks); }, getMapper: (mapperName: string) => { if (!module.isConnected()) { const emptyMapper = null; return emptyMapper; } return mappers[mapperName](module); }, getMappers: (...mapperNames: string[]) => { if (!module.isConnected()) { const result: Record<string, MapperResult> = {}; forEach((mapperName) => { result[mapperName] = emptyMapper; }, mapperNames); return result; } const result: Record<string, Mapper> = {}; forEach((mapperName) => { result[mapperName] = mappers[mapperName](module); }, mapperNames); return result; }, getAllMappers: (): Record<string, MapperResult> => { if (!module.isConnected()) { return mapValues(() => emptyMapper, mappers); } return mapValues((mapper) => mapper(module), mappers); }, setMapper: (mapperName: string, mapper: Mapper) => { mappers[mapperName] = mapper; }, removeMapper: (mapperName: string) => { mappers = omit([mapperName], mappers); }, clearMappers: () => { mappers = {}; }, destroy: () => { baseModule.destroy(); module.clearMappers(); }, }); return module; }