@quenty/inputkeymaputils 4.2.1-canary.256.edbbcfc.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,7 +3,15 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ## [4.2.1-canary.256.edbbcfc.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/inputkeymaputils@4.2.0...@quenty/inputkeymaputils@4.2.1-canary.256.edbbcfc.0) (2022-03-27)
6
+ # [5.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/inputkeymaputils@4.3.0...@quenty/inputkeymaputils@5.0.0) (2022-05-21)
7
+
8
+ **Note:** Version bump only for package @quenty/inputkeymaputils
9
+
10
+
11
+
12
+
13
+
14
+ # [4.3.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/inputkeymaputils@4.2.0...@quenty/inputkeymaputils@4.3.0) (2022-03-27)
7
15
 
8
16
  **Note:** Version bump only for package @quenty/inputkeymaputils
9
17
 
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2014-2021 Quenty
3
+ Copyright (c) 2014-2022 Quenty
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -13,9 +13,13 @@
13
13
 
14
14
  Utility methods for input map
15
15
 
16
- <div align="center"><a href="https://quenty.github.io/NevermoreEngine/api/InputKeyMapUtils">View docs →</a></div>
16
+ <div align="center"><a href="https://quenty.github.io/NevermoreEngine/api/InputKeyMapList">View docs →</a></div>
17
17
 
18
18
  ## Installation
19
19
  ```
20
20
  npm install @quenty/inputkeymaputils --save
21
- ```
21
+ ```
22
+
23
+ ## Design
24
+
25
+ Note this system is designed to simple hold data, it doesn't do any binding with that data. So basically, an InputKeyMap can hold the information on what to bind, and what preferences are in a structured way.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/inputkeymaputils",
3
- "version": "4.2.1-canary.256.edbbcfc.0",
3
+ "version": "5.0.0",
4
4
  "description": "Utility methods for input map",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -26,12 +26,21 @@
26
26
  "Quenty"
27
27
  ],
28
28
  "dependencies": {
29
- "@quenty/inputmode": "4.1.1-canary.256.edbbcfc.0",
30
- "@quenty/loader": "4.0.1-canary.256.edbbcfc.0",
31
- "@quenty/table": "2.1.2-canary.256.edbbcfc.0"
29
+ "@quenty/baseobject": "^5.0.0",
30
+ "@quenty/brio": "^6.0.0",
31
+ "@quenty/inputmode": "^5.0.0",
32
+ "@quenty/loader": "^5.0.0",
33
+ "@quenty/maid": "^2.3.0",
34
+ "@quenty/observablecollection": "^3.0.0",
35
+ "@quenty/rx": "^5.0.0",
36
+ "@quenty/servicebag": "^5.0.0",
37
+ "@quenty/statestack": "^6.0.0",
38
+ "@quenty/table": "^3.0.0",
39
+ "@quenty/valuebaseutils": "^5.0.0",
40
+ "@quenty/valueobject": "^5.0.0"
32
41
  },
33
42
  "publishConfig": {
34
43
  "access": "public"
35
44
  },
36
- "gitHead": "edbbcfc38516772a791d50dc43cd6b304ffc4aff"
45
+ "gitHead": "9f7eaea7543c33c89d2e32c38491b13f9271f4f7"
37
46
  }
@@ -0,0 +1,55 @@
1
+ --[=[
2
+ This represents a list of key bindings for a specific mode. While this is a useful object to query
3
+ for showing icons and input hints to the user, in general, it is recommended that binding occur
4
+ at the list level instead of at the input mode level. That way, if the user switches to another input
5
+ mode then input is immediately processed.
6
+
7
+ @class InputKeyMap
8
+ ]=]
9
+
10
+ local require = require(script.Parent.loader).load(script)
11
+
12
+ local BaseObject = require("BaseObject")
13
+ local ValueObject = require("ValueObject")
14
+ local InputMode = require("InputMode")
15
+
16
+ local InputKeyMap = setmetatable({}, BaseObject)
17
+ InputKeyMap.ClassName = "InputKeyMap"
18
+ InputKeyMap.__index = InputKeyMap
19
+
20
+ function InputKeyMap.new(inputMode, inputTypes)
21
+ assert(InputMode.isInputMode(inputMode), "Bad inputMode")
22
+ assert(type(inputTypes) == "table" or inputTypes == nil, "Bad inputTypes")
23
+
24
+ local self = setmetatable(BaseObject.new(), InputKeyMap)
25
+
26
+ self._inputMode = assert(inputMode, "No inputMode")
27
+
28
+ self._inputType = ValueObject.new(inputTypes or {})
29
+ self._maid:GiveTask(self._inputType)
30
+
31
+ return self
32
+ end
33
+
34
+ --[=[
35
+ Gets the input mode for this keymap. This will not change.
36
+ ]=]
37
+ function InputKeyMap:GetInputMode()
38
+ return self._inputMode
39
+ end
40
+
41
+ function InputKeyMap:SetInputTypesList(inputTypes)
42
+ assert(type(inputTypes) == "table", "Bad inputTypes")
43
+
44
+ self._inputType.Value = inputTypes
45
+ end
46
+
47
+ function InputKeyMap:ObserveInputTypesList()
48
+ return self._inputType:Observe()
49
+ end
50
+
51
+ function InputKeyMap:GetInputTypesList()
52
+ return self._inputType.Value
53
+ end
54
+
55
+ return InputKeyMap
@@ -0,0 +1,364 @@
1
+ --[=[
2
+ An input key map list provides a mapping of input modes to input keys.
3
+ One of these should generally exist per an action with unique bindings.
4
+
5
+ All inputs should be bound while this action is active. We can further
6
+ query inputs per an input mode to display only relevant key bindings to
7
+ the user.
8
+
9
+ ```lua
10
+ local inputKeyMapList = InputKeyMapList.new("BOOST", {
11
+ InputKeyMap.new(INPUT_MODES.KeyboardAndMouse, { Enum.KeyCode.LeftControl });
12
+ InputKeyMap.new(INPUT_MODES.Gamepads, { Enum.KeyCode.ButtonX });
13
+ InputKeyMap.new(INPUT_MODES.Touch, { SlottedTouchButtonUtils.createSlottedTouchButton("primary1") });
14
+ })
15
+
16
+ maid:GiveTask(Rx.combineLatest({
17
+ isRobloxTouchButton = inputKeyMapList:ObserveIsRobloxTouchButton();
18
+ inputEnumsList = inputKeyMapList:ObserveInputEnumsList();
19
+ }):Subscribe(function(state)
20
+ maid._contextMaid = nil
21
+
22
+ local contextMaid = Maid.new()
23
+
24
+ ContextActionService:BindActionAtPriority(
25
+ "MyAction",
26
+ function(_actionName, userInputState, inputObject)
27
+ print("Process input", inputObject)
28
+ end,
29
+ state.isRobloxTouchButton,
30
+ Enum.ContextActionPriority.High.Value,
31
+ unpack(state.inputEnumsList))
32
+
33
+ maid._contextMaid = contextMaid
34
+ end))
35
+ end))
36
+ ```
37
+
38
+ @class InputKeyMapList
39
+ ]=]
40
+
41
+ local require = require(script.Parent.loader).load(script)
42
+
43
+ local InputKeyMap = require("InputKeyMap")
44
+ local ObservableMap = require("ObservableMap")
45
+ local BaseObject = require("BaseObject")
46
+ local InputModeSelector = require("InputModeSelector")
47
+ local Observable = require("Observable")
48
+ local Maid = require("Maid")
49
+ local Rx = require("Rx")
50
+ local ObservableCountingMap = require("ObservableCountingMap")
51
+ local InputMode = require("InputMode")
52
+ local SlottedTouchButtonUtils = require("SlottedTouchButtonUtils")
53
+ local RxBrioUtils = require("RxBrioUtils")
54
+ local Brio = require("Brio")
55
+ local StateStack = require("StateStack")
56
+ local InputTypeUtils = require("InputTypeUtils")
57
+
58
+ local InputKeyMapList = setmetatable({}, BaseObject)
59
+ InputKeyMapList.ClassName = "InputKeyMapList"
60
+ InputKeyMapList.__index = InputKeyMapList
61
+
62
+ --[=[
63
+ Constructs a new InputKeyMapList
64
+
65
+ @param inputMapName string
66
+ @param inputKeyMapList { InputKeyMap }
67
+ @return InputKeyMapList
68
+ ]=]
69
+ function InputKeyMapList.new(inputMapName, inputKeyMapList)
70
+ local self = setmetatable(BaseObject.new(), InputKeyMapList)
71
+
72
+ self._inputKeyMapListName = assert(inputMapName, "No inputMapName")
73
+
74
+ self._inputModeToInputKeyMap = ObservableMap.new()
75
+ self._maid:GiveTask(self._inputModeToInputKeyMap)
76
+
77
+ for _, inputKeyMap in pairs(inputKeyMapList) do
78
+ self:Add(inputKeyMap)
79
+ end
80
+
81
+ return self
82
+ end
83
+
84
+ --[=[
85
+ Returns whether this value is an InputKeyMapList
86
+
87
+ @param value any
88
+ @return boolean
89
+ ]=]
90
+ function InputKeyMapList.isInputKeyMapList(value)
91
+ return type(value) == "table" and getmetatable(value) == InputKeyMapList
92
+ end
93
+
94
+ --[=[
95
+ Adds an input key map into the actual list
96
+ @param inputKeyMap InputKeyMap
97
+ ]=]
98
+ function InputKeyMapList:Add(inputKeyMap)
99
+ assert(inputKeyMap, "Bad inputKeyMap")
100
+
101
+ self._maid[inputKeyMap:GetInputMode()] = inputKeyMap
102
+ self._inputModeToInputKeyMap:Set(inputKeyMap:GetInputMode(), inputKeyMap)
103
+ end
104
+
105
+ --[=[
106
+ Gets the list name and returns it. Used by an input key map provider
107
+ @return string
108
+ ]=]
109
+ function InputKeyMapList:GetListName()
110
+ return self._inputKeyMapListName
111
+ end
112
+
113
+ function InputKeyMapList:SetInputTypesList(inputMode, inputTypes)
114
+ assert(InputMode.isInputMode(inputMode), "Bad inputMode")
115
+ assert(type(inputTypes) == "table" or inputTypes == nil, "Bad inputTypes")
116
+
117
+ if inputTypes == nil then
118
+ self._inputModeToInputKeyMap:Remove(inputMode)
119
+ self._maid[inputMode] = nil
120
+ else
121
+ local inputKeyMap = self._inputModeToInputKeyMap:Get(inputMode)
122
+ if not inputKeyMap then
123
+ self:Add(InputKeyMap.new(inputMode, inputTypes))
124
+ else
125
+ inputKeyMap:SetInputTypesList(inputTypes)
126
+ end
127
+ end
128
+ end
129
+
130
+ --[=[
131
+ Removes the entry for the inputmode
132
+
133
+ @param inputMode InputMode
134
+ ]=]
135
+ function InputKeyMapList:RemoveInputMode(inputMode)
136
+ assert(InputMode.isInputMode(inputMode), "Bad inputMode")
137
+
138
+ self:SetInputTypesList(inputMode, nil)
139
+ end
140
+
141
+ --[=[
142
+ Observes the input enums list
143
+
144
+ @return InputModeSelector
145
+ ]=]
146
+ function InputKeyMapList:GetNewInputModeSelector()
147
+ return InputModeSelector.fromObservableBrio(self:ObserveInputModesBrio())
148
+ end
149
+
150
+ --[=[
151
+ @return Observable<Brio<InputKeyMap>>
152
+ ]=]
153
+ function InputKeyMapList:ObserveInputKeyMapsBrio()
154
+ return self._inputModeToInputKeyMap:ObserveValuesBrio()
155
+ end
156
+
157
+ --[=[
158
+ @return Observable<Brio<InputMode>>
159
+ ]=]
160
+ function InputKeyMapList:ObserveInputModesBrio()
161
+ return self._inputModeToInputKeyMap:ObserveKeysBrio()
162
+ end
163
+
164
+ --[=[
165
+ Observes the input types for the active input map
166
+
167
+ @return Observable<InputKeyMap>
168
+ ]=]
169
+ function InputKeyMapList:ObserveActiveInputKeyMap()
170
+ return self:ObserveActiveInputMode():Pipe({
171
+ Rx.switchMap(function(activeInputMode)
172
+ if activeInputMode then
173
+ return self._inputModeToInputKeyMap:ObserveValueForKey(activeInputMode)
174
+ else
175
+ return Rx.of(nil)
176
+ end
177
+ end);
178
+ })
179
+ end
180
+
181
+ --[=[
182
+ Observes the input types for the active input map.
183
+
184
+ :::warning
185
+ This should be used for hinting inputs, but it's preferred to
186
+ bind inputs for all modes. See [InputKeyMapList.ObserveInputEnumsList]
187
+ :::
188
+
189
+ @return Observable<{ InputType }?>
190
+ ]=]
191
+ function InputKeyMapList:ObserveActiveInputTypesList()
192
+ return self:ObserveActiveInputKeyMap():Pipe({
193
+ Rx.switchMap(function(activeInputMap)
194
+ if activeInputMap then
195
+ return activeInputMap:ObserveInputTypesList()
196
+ else
197
+ return Rx.of(nil)
198
+ end
199
+ end);
200
+ Rx.distinct();
201
+ })
202
+ end
203
+
204
+ --[=[
205
+ Observes the active input mode currently selected.
206
+
207
+ @return Observable<InputMode?>
208
+ ]=]
209
+ function InputKeyMapList:ObserveActiveInputMode()
210
+ return Observable.new(function(sub)
211
+ local maid = Maid.new()
212
+
213
+ local selector = self:GetNewInputModeSelector()
214
+ maid:GiveTask(selector)
215
+
216
+ maid:GiveTask(selector.Changed:Connect(function()
217
+ sub:Fire(selector.Value)
218
+ end))
219
+ sub:Fire(selector.Value)
220
+
221
+ return maid
222
+ end)
223
+ end
224
+
225
+ --[=[
226
+ Observes whether the input list includes tapping in the world somewhere.
227
+
228
+ @return Observable<boolean>
229
+ ]=]
230
+ function InputKeyMapList:ObserveIsTapInWorld()
231
+ self:_ensureInit()
232
+
233
+ return self._isTapInWorld:Observe()
234
+ end
235
+
236
+ --[=[
237
+ Observes whether the input list includes a Roblox button.
238
+
239
+ @return Observable<boolean>
240
+ ]=]
241
+ function InputKeyMapList:ObserveIsRobloxTouchButton()
242
+ self:_ensureInit()
243
+
244
+ return self._isRobloxTouchButton:Observe()
245
+ end
246
+
247
+ --[=[
248
+ Gets whether the input list includes a Roblox button.
249
+
250
+ @return boolean
251
+ ]=]
252
+ function InputKeyMapList:IsRobloxTouchButton()
253
+ self:_ensureInit()
254
+
255
+ return self._isRobloxTouchButton:GetState()
256
+ end
257
+
258
+ --[=[
259
+ Gets whether the input list includes a Roblox button.
260
+
261
+ @return boolean
262
+ ]=]
263
+ function InputKeyMapList:IsTouchTapInWorld()
264
+ self:_ensureInit()
265
+
266
+ return self._isTapInWorld:GetState()
267
+ end
268
+
269
+ --[=[
270
+ Observes the input enums list, which can be used for bindings.
271
+
272
+ @return Observable<{UserInputType | KeyCode}>
273
+ ]=]
274
+ function InputKeyMapList:ObserveInputEnumsList()
275
+ self:_ensureInit()
276
+
277
+ return self._inputTypesForBinding:ObserveKeysList()
278
+ end
279
+
280
+ --[=[
281
+ Observes the input enums set
282
+
283
+ @return Observable<{[UserInputType | KeyCode]: true }>
284
+ ]=]
285
+ function InputKeyMapList:ObserveInputEnumsSet()
286
+ self:_ensureInit()
287
+
288
+ return self._inputTypesForBinding:ObserveKeysSet()
289
+ end
290
+
291
+ --[=[
292
+ Observes slotted touch button data in the input modes.
293
+
294
+ @return Observable<SlottedTouchButton>
295
+ ]=]
296
+ function InputKeyMapList:ObserveSlottedTouchButtonDataBrio()
297
+ return self._inputModeToInputKeyMap:ObservePairsBrio():Pipe({
298
+ RxBrioUtils.flatMapBrio(function(inputMode, inputKeyMap)
299
+ return inputKeyMap:ObserveInputTypesList():Pipe({
300
+ Rx.switchMap(function(inputTypesList)
301
+ local valid = {}
302
+ for _, inputType in pairs(inputTypesList) do
303
+ if SlottedTouchButtonUtils.isSlottedTouchButton(inputType) then
304
+ local data = SlottedTouchButtonUtils.createTouchButtonData(inputType.slotId, inputMode)
305
+ table.insert(valid, Brio.new(data))
306
+ end
307
+ end
308
+
309
+ if not next(valid) then
310
+ return Rx.EMPTY
311
+ else
312
+ return Rx.of(unpack(valid))
313
+ end
314
+ end)
315
+ })
316
+ end);
317
+ })
318
+ end
319
+
320
+ function InputKeyMapList:_ensureInit()
321
+ if self._inputTypesForBinding then
322
+ return self._inputTypesForBinding
323
+ end
324
+
325
+ self._inputTypesForBinding = ObservableCountingMap.new()
326
+ self._maid:GiveTask(self._inputTypesForBinding)
327
+
328
+ self._isTapInWorld = StateStack.new(false)
329
+ self._maid:GiveTask(self._isTapInWorld)
330
+
331
+ self._isRobloxTouchButton = StateStack.new(false)
332
+ self._maid:GiveTask(self._isRobloxTouchButton)
333
+
334
+ -- Listen
335
+ self._maid:GiveTask(self._inputModeToInputKeyMap:ObserveValuesBrio():Subscribe(function(brio)
336
+ if brio:IsDead() then
337
+ return
338
+ end
339
+
340
+ local inputKeyMapMaid = brio:ToMaid()
341
+ local inputKeyMap = brio:GetValue()
342
+
343
+ inputKeyMapMaid:GiveTask(inputKeyMap:ObserveInputTypesList():Subscribe(function(inputTypes)
344
+ local maid = Maid.new()
345
+
346
+ for _, inputType in pairs(inputTypes) do
347
+ -- only emit enum items
348
+ if typeof(inputType) == "EnumItem" then
349
+ maid:GiveTask(self._inputTypesForBinding:Add(inputType))
350
+ elseif InputTypeUtils.isTapInWorld(inputType) then
351
+ maid:GiveTask(self._isTapInWorld:PushState(true))
352
+ elseif InputTypeUtils.isRobloxTouchButton(inputType) then
353
+ maid:GiveTask(self._isRobloxTouchButton:PushState(true))
354
+ end
355
+ end
356
+
357
+ inputKeyMapMaid._current = maid
358
+ end))
359
+ end))
360
+
361
+ return self._inputTypesForBinding
362
+ end
363
+
364
+ return InputKeyMapList
@@ -0,0 +1,147 @@
1
+ --[=[
2
+ Centralizes input of keys. You can construct a new provider in a
3
+ package and key bindings can be recovered from it. This is designed
4
+ for user configuration/rebindings.
5
+
6
+ ```lua
7
+ local inputMapProvider = InputKeyMapListProvider.new("General", function(self)
8
+ self:Add(InputKeyMapList.new("JUMP", {
9
+ InputKeyMap.new(INPUT_MODES.KeyboardAndMouse, { Enum.KeyCode.Space });
10
+ InputKeyMap.new(INPUT_MODES.Gamepads, { Enum.KeyCode.ButtonA });
11
+ InputKeyMap.new(INPUT_MODES.Touch, { SlottedTouchButtonUtils.createSlottedTouchButton("primary3") });
12
+ }))
13
+ self:Add(InputKeyMapList.new("HONK", {
14
+ InputKeyMap.new(INPUT_MODES.KeyboardAndMouse, { Enum.KeyCode.H });
15
+ InputKeyMap.new(INPUT_MODES.Gamepads, { Enum.KeyCode.DPadUp });
16
+ InputKeyMap.new(INPUT_MODES.Touch, { SlottedTouchButtonUtils.createSlottedTouchButton("primary2") });
17
+ }))
18
+ self:Add(InputKeyMapList.new("BOOST", {
19
+ InputKeyMap.new(INPUT_MODES.KeyboardAndMouse, { Enum.KeyCode.LeftControl });
20
+ InputKeyMap.new(INPUT_MODES.Gamepads, { Enum.KeyCode.ButtonX });
21
+ InputKeyMap.new(INPUT_MODES.Touch, { SlottedTouchButtonUtils.createSlottedTouchButton("primary4") });
22
+ }))
23
+ end)
24
+
25
+ local inputMap = serviceBag:GetService(inputMapProvider)
26
+
27
+ serviceBag:Init()
28
+ serviceBag:Start()
29
+ ```
30
+
31
+ @class InputKeyMapListProvider
32
+ ]=]
33
+
34
+ local require = require(script.Parent.loader).load(script)
35
+
36
+ local RunService = game:GetService("RunService")
37
+
38
+ local Maid = require("Maid")
39
+ local InputKeyMapServiceClient = require("InputKeyMapServiceClient")
40
+
41
+ local InputKeyMapListProvider = {}
42
+ InputKeyMapListProvider.ClassName = "InputKeyMapListProvider"
43
+ InputKeyMapListProvider.__index = InputKeyMapListProvider
44
+
45
+ --[=[
46
+ Constructs a new InputKeyMapListProvider. The name will be used for retrieval,
47
+ for example, if the dialog system needs to get a general input hint to show
48
+ to the user.
49
+
50
+ @param providerName string -- Name to use for global specification.
51
+ @param createDefaults callback -- Callback to construct the default items on init
52
+ @return InputKeyMapList
53
+ ]=]
54
+ function InputKeyMapListProvider.new(providerName, createDefaults)
55
+ local self = setmetatable({}, InputKeyMapListProvider)
56
+
57
+ self._providerName = assert(providerName, "No providerName")
58
+ self._createDefaults = assert(createDefaults, "No createDefaults")
59
+
60
+ return self
61
+ end
62
+
63
+ --[=[
64
+ Gets this providers name
65
+ @return string
66
+ ]=]
67
+ function InputKeyMapListProvider:GetProviderName()
68
+ return self._providerName
69
+ end
70
+
71
+ --[=[
72
+ Gets an input key map list for the given name. Errors if it is not
73
+ defined.
74
+
75
+ @param keyMapListName string
76
+ @return InputKeyMapList
77
+ ]=]
78
+ function InputKeyMapListProvider:GetInputKeyMapList(keyMapListName)
79
+ local keyMapList = self:FindInputKeyMapList(keyMapListName)
80
+ if not keyMapList then
81
+ error(("Bad keyMapListName %q"):format(tostring(keyMapListName)))
82
+ end
83
+
84
+ return keyMapList
85
+ end
86
+
87
+ --[=[
88
+ Finds an input key map list for the given name
89
+ @param keyMapListName string
90
+ @return InputKeyMapList
91
+ ]=]
92
+ function InputKeyMapListProvider:FindInputKeyMapList(keyMapListName)
93
+ assert(type(keyMapListName) == "string", "Bad keyMapListName")
94
+
95
+ if not self._inputKeyMapLists then
96
+ if not RunService:IsRunning() then
97
+ -- Test mode initialize
98
+ self._maid = Maid.new()
99
+ self:_ensureDefaultsInit()
100
+ else
101
+ error("Not initialized, make sure to retrieve via serviceBag and init")
102
+ end
103
+ end
104
+
105
+ return self._inputKeyMapLists[keyMapListName]
106
+ end
107
+
108
+ function InputKeyMapListProvider:Add(inputKeyMapList)
109
+ assert(inputKeyMapList, "Bad inputKeyMapList")
110
+ assert(self._maid, "Not initialized")
111
+
112
+ if self._inputKeyMapLists[inputKeyMapList:GetListName()] then
113
+ error(("Already added %q"):format(inputKeyMapList:GetListName()))
114
+ end
115
+
116
+ self._inputKeyMapLists[inputKeyMapList:GetListName()] = inputKeyMapList
117
+ self._maid:GiveTask(inputKeyMapList)
118
+ end
119
+
120
+ function InputKeyMapListProvider:Init(serviceBag)
121
+ assert(not self._serviceBag, "Already initialized")
122
+
123
+ self._serviceBag = assert(serviceBag, "No serviceBag")
124
+ self._serviceBag:GetService(InputKeyMapServiceClient):RegisterProvider(self)
125
+ self._maid = Maid.new()
126
+
127
+ self:_ensureDefaultsInit()
128
+ end
129
+
130
+ function InputKeyMapListProvider:_ensureDefaultsInit()
131
+ if not self._inputKeyMapLists then
132
+ self._inputKeyMapLists = {}
133
+
134
+ self._createDefaults(self, self._serviceBag)
135
+ end
136
+ end
137
+
138
+ function InputKeyMapListProvider:Start()
139
+ -- empty function
140
+ end
141
+
142
+ function InputKeyMapListProvider:Destroy()
143
+ self._maid:DoCleaning()
144
+ self._inputKeyMapLists = nil
145
+ end
146
+
147
+ return InputKeyMapListProvider
@@ -0,0 +1,66 @@
1
+ --[=[
2
+ Not required to be initialized
3
+ @class InputKeyMapServiceClient
4
+ ]=]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local RunService = game:GetService("RunService")
9
+
10
+ local InputKeyMapServiceClient = {}
11
+
12
+ function InputKeyMapServiceClient:Init(serviceBag)
13
+ assert(not self._serviceBag, "Already initialized")
14
+ self._serviceBag = assert(serviceBag, "No serviceBag")
15
+
16
+ self._providers = {}
17
+ end
18
+
19
+ function InputKeyMapServiceClient:RegisterProvider(provider)
20
+ assert(provider, "Bad provider")
21
+ assert(self._providers, "Not initialized")
22
+
23
+ local providerName = provider:GetProviderName()
24
+ if self._providers[providerName] then
25
+ error(("Already have a provider with name %q"):format(providerName))
26
+ end
27
+
28
+ self._providers[providerName] = provider
29
+ end
30
+
31
+ function InputKeyMapServiceClient:GetProvider(providerName)
32
+ assert(type(providerName) == "string", "Bad providerName")
33
+
34
+ return self._providers[providerName]
35
+ end
36
+
37
+ -- function InputKeyMapServiceClient:ObserveInputKeyMapList(providerName, inputKeyMapListName)
38
+ -- assert(type(providerName) == "string", "Bad providerName")
39
+ -- assert(type(inputKeyMapListName) == "string", "Bad inputKeyMapListName")
40
+
41
+ -- end
42
+
43
+ function InputKeyMapServiceClient:FindInputKeyMapList(providerName, inputKeyMapListName)
44
+ assert(type(providerName) == "string", "Bad providerName")
45
+ assert(type(inputKeyMapListName) == "string", "Bad inputKeyMapListName")
46
+
47
+ if not RunService:IsRunning() then
48
+ return nil
49
+ end
50
+
51
+ assert(self._providers, "Not initialized")
52
+ for _, provider in pairs(self._providers) do
53
+ if provider:GetProviderName() == providerName then
54
+ local found = provider:FindInputKeyMapList(inputKeyMapListName)
55
+ if found then
56
+ return found
57
+ end
58
+ end
59
+ end
60
+
61
+ return nil
62
+ end
63
+
64
+
65
+
66
+ return InputKeyMapServiceClient
@@ -6,8 +6,9 @@
6
6
 
7
7
  local require = require(script.Parent.loader).load(script)
8
8
 
9
- local InputKeyMapUtils = require("InputKeyMapUtils")
9
+ local InputKeyMapList = require("InputKeyMapList")
10
10
  local INPUT_MODES = require("INPUT_MODES")
11
+ local InputKeyMap = require("InputKeyMap")
11
12
 
12
13
  local ProximityPromptInputUtils = {}
13
14
 
@@ -17,13 +18,13 @@ local ProximityPromptInputUtils = {}
17
18
  @param prompt ProximityPrompt
18
19
  @return InputKeyMapList
19
20
  ]=]
20
- function ProximityPromptInputUtils.inputKeyMapFromPrompt(prompt)
21
+ function ProximityPromptInputUtils.newInputKeyMapFromPrompt(prompt)
21
22
  assert(typeof(prompt) == "Instance", "Bad prompt")
22
23
 
23
- return {
24
- InputKeyMapUtils.createKeyMap(INPUT_MODES.Gamepads, { prompt.GamepadKeyCode });
25
- InputKeyMapUtils.createKeyMap(INPUT_MODES.Keyboard, { prompt.KeyboardKeyCode })
26
- }
24
+ return InputKeyMapList.new("custom", {
25
+ InputKeyMap.new(INPUT_MODES.Gamepads, { prompt.GamepadKeyCode });
26
+ InputKeyMap.new(INPUT_MODES.Keyboard, { prompt.KeyboardKeyCode })
27
+ })
27
28
  end
28
29
 
29
30
 
@@ -0,0 +1,67 @@
1
+ --[=[
2
+ @class InputTypeUtils
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local SlottedTouchButtonUtils = require("SlottedTouchButtonUtils")
8
+
9
+ local InputTypeUtils = {}
10
+
11
+ --[=[
12
+ A valid input type that can be represented here.
13
+ @type InputType KeyCode | UserInputType | SlottedTouchButton | "TouchButton" | "Tap" | any
14
+ @within InputTypeUtils
15
+ ]=]
16
+
17
+ --[=[
18
+ Returns true if the input type is specifying a tap in the world
19
+ @param inputKey any
20
+ @return boolean
21
+ ]=]
22
+ function InputTypeUtils.isTapInWorld(inputKey)
23
+ return inputKey == "Tap"
24
+ end
25
+
26
+ --[=[
27
+ Returns true if the input type is specifying a Roblox touch button
28
+ @param inputKey any
29
+ @return boolean
30
+ ]=]
31
+ function InputTypeUtils.isRobloxTouchButton(inputKey)
32
+ return inputKey == "TouchButton"
33
+ end
34
+
35
+ --[=[
36
+ Specifies a tap in the world
37
+ @return "Tap"
38
+ ]=]
39
+ function InputTypeUtils.createTapInWorld()
40
+ return "Tap"
41
+ end
42
+
43
+ --[=[
44
+ Specifies a roblox touch button
45
+ @return "Tap"
46
+ ]=]
47
+ function InputTypeUtils.createRobloxTouchButton()
48
+ return "TouchButton"
49
+ end
50
+
51
+ --[=[
52
+ Computes a unique id for an inputType which can be used
53
+ in a set to deduplicate/compare the objects. Used to know
54
+ when to exclude different types from each other.
55
+
56
+ @param inputType InputType
57
+ @return any
58
+ ]=]
59
+ function InputTypeUtils.getUniqueKeyForInputType(inputType)
60
+ if SlottedTouchButtonUtils.isSlottedTouchButton(inputType) then
61
+ return inputType.slotId
62
+ else
63
+ return inputType
64
+ end
65
+ end
66
+
67
+ return InputTypeUtils
@@ -0,0 +1,98 @@
1
+ --[=[
2
+ @class SlottedTouchButtonUtils
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local SlottedTouchButtonUtils = {}
8
+
9
+
10
+ --[=[
11
+ Internal data representing a slotted touch button
12
+ @interface SlottedTouchButtonData
13
+ .slotId string
14
+ .inputMode InputMode
15
+ @within SlottedTouchButtonUtils
16
+ ]=]
17
+
18
+
19
+ --[=[
20
+ A touch button that goes into a specific slot. This ensures
21
+ consistent slot positions.
22
+
23
+ @interface SlottedTouchButton
24
+ .type "SlottedTouchButton"
25
+ .slotId string
26
+ @within SlottedTouchButtonUtils
27
+ ]=]
28
+
29
+ --[=[
30
+ Touch buttons should always show up in the same position
31
+ We use the SlotId to determine which slot we should put
32
+ these buttons in.
33
+
34
+ @param slotId string
35
+ @return SlottedTouchButton
36
+ ]=]
37
+ function SlottedTouchButtonUtils.createSlottedTouchButton(slotId)
38
+ assert(slotId == "primary1"
39
+ or slotId == "primary2"
40
+ or slotId == "primary3"
41
+ or slotId == "primary4"
42
+ or slotId == "touchpad1", "Bad slotId")
43
+
44
+ return {
45
+ type = "SlottedTouchButton";
46
+ slotId = slotId;
47
+ }
48
+ end
49
+
50
+ --[=[
51
+ Returns whether an inputType is a SlottedTouchButton type
52
+
53
+ @param inputType any
54
+ @return boolean
55
+ ]=]
56
+ function SlottedTouchButtonUtils.isSlottedTouchButton(inputType)
57
+ return type(inputType) == "table" and inputType.type == "SlottedTouchButton"
58
+ end
59
+
60
+ --[=[
61
+ Gets slotted touch button data for an inputKeyMapList
62
+
63
+ @param slotId string
64
+ @param inputMode InputMode
65
+ @return SlottedTouchButtonData
66
+ ]=]
67
+ function SlottedTouchButtonUtils.createTouchButtonData(slotId, inputMode)
68
+ return {
69
+ slotId = slotId;
70
+ inputMode = inputMode;
71
+ }
72
+ end
73
+
74
+ --[=[
75
+ Gets slotted touch button data for an inputKeyMapList
76
+
77
+ @param inputKeyMapList InputKeyMapList
78
+ @return { SlottedTouchButtonData }
79
+ ]=]
80
+ function SlottedTouchButtonUtils.getSlottedTouchButtonData(inputKeyMapList)
81
+ local slottedTouchButtons = {}
82
+
83
+ for _, inputKeyMap in pairs(inputKeyMapList) do
84
+ assert(inputKeyMap.inputMode, "Bad inputKeyMap.inputMode")
85
+ assert(inputKeyMap.inputTypes, "Bad inputKeyMap.inputTypes")
86
+
87
+ for _, touchButtonData in pairs(inputKeyMap.inputTypes) do
88
+ if SlottedTouchButtonUtils.isSlottedTouchButton(touchButtonData) then
89
+ table.insert(slottedTouchButtons, SlottedTouchButtonUtils.createTouchButtonData(
90
+ touchButtonData.slotId, inputKeyMap.inputMode))
91
+ end
92
+ end
93
+ end
94
+
95
+ return slottedTouchButtons
96
+ end
97
+
98
+ return SlottedTouchButtonUtils
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "InputKeyMapUtilsTest",
3
+ "tree": {
4
+ "$className": "DataModel",
5
+ "ServerScriptService": {
6
+ "inputkeymaputils": {
7
+ "$className": "Folder",
8
+ "inputkeymaputils": {
9
+ "$path": ".."
10
+ },
11
+ "test": {
12
+ "$path": "modules"
13
+ }
14
+ },
15
+ "Script": {
16
+ "$path": "scripts/Server"
17
+ }
18
+ },
19
+ "StarterPlayer": {
20
+ "StarterPlayerScripts": {
21
+ "Main": {
22
+ "$path": "scripts/Client"
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,25 @@
1
+ --[=[
2
+ Test input key map provider
3
+ @class TestInputKeyMap
4
+ ]=]
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local INPUT_MODES = require("INPUT_MODES")
8
+ local InputKeyMap = require("InputKeyMap")
9
+ local InputKeyMapList = require("InputKeyMapList")
10
+ local InputKeyMapListProvider = require("InputKeyMapListProvider")
11
+ local SlottedTouchButtonUtils = require("SlottedTouchButtonUtils")
12
+
13
+ return InputKeyMapListProvider.new(script.Name, function(self)
14
+ self:Add(InputKeyMapList.new("JUMP", {
15
+ InputKeyMap.new(INPUT_MODES.KeyboardAndMouse, { Enum.KeyCode.Q });
16
+ InputKeyMap.new(INPUT_MODES.Gamepads, { Enum.KeyCode.ButtonY });
17
+ InputKeyMap.new(INPUT_MODES.Touch, { SlottedTouchButtonUtils.createSlottedTouchButton("primary3") });
18
+ }))
19
+
20
+ self:Add(InputKeyMapList.new("HONK", {
21
+ InputKeyMap.new(INPUT_MODES.KeyboardAndMouse, { Enum.KeyCode.H });
22
+ InputKeyMap.new(INPUT_MODES.Gamepads, { Enum.KeyCode.ButtonL1 });
23
+ InputKeyMap.new(INPUT_MODES.Touch, { SlottedTouchButtonUtils.createSlottedTouchButton("primary2") });
24
+ }))
25
+ end)
@@ -0,0 +1,28 @@
1
+ --[[
2
+ @class ClientMain
3
+ ]]
4
+ local packages = game:GetService("ReplicatedStorage"):WaitForChild("Packages")
5
+
6
+ local ContextActionService = game:GetService("ContextActionService")
7
+
8
+ local INPUT_MODES = require(packages.INPUT_MODES)
9
+ local serviceBag = require(packages.ServiceBag).new()
10
+
11
+ serviceBag:GetService(packages.InputKeyMapServiceClient)
12
+ local inputKeyMap = serviceBag:GetService(packages.TestInputKeyMap)
13
+
14
+ -- Start game
15
+ serviceBag:Init()
16
+ serviceBag:Start()
17
+
18
+ local keyMapList = inputKeyMap:GetInputKeyMapList("HONK")
19
+
20
+ keyMapList:ObserveInputEnumsList():Subscribe(function(...)
21
+ print("activeInputTypes", ...)
22
+ ContextActionService:BindAction("actionTypes", function(_, _, inputObject)
23
+ print("Activated", inputObject.UserInputState)
24
+ end, false, ...)
25
+ end)
26
+
27
+
28
+ keyMapList:SetForInputMode(INPUT_MODES.Keypad, { Enum.KeyCode.Space })
@@ -0,0 +1,7 @@
1
+ --[[
2
+ @class ServerMain
3
+ ]]
4
+ local ServerScriptService = game:GetService("ServerScriptService")
5
+
6
+ local loader = ServerScriptService:FindFirstChild("LoaderUtils", true).Parent
7
+ require(loader).bootstrapGame(ServerScriptService.inputkeymaputils)
@@ -1,320 +0,0 @@
1
- --[=[
2
- Utility methods for input. Centralizes input. In the future, this will allow
3
- user configuration.
4
-
5
- ```lua
6
- local inputMap = {
7
- JUMP = {
8
- InputKeyMapUtils.createKeyMap(INPUT_MODES.KeyboardAndMouse, { Enum.KeyCode.Space });
9
- InputKeyMapUtils.createKeyMap(INPUT_MODES.Gamepads, { Enum.KeyCode.ButtonA });
10
- InputKeyMapUtils.createKeyMap(INPUT_MODES.Touch, { InputKeyMapUtils.createSlottedTouchButton("primary3") });
11
- };
12
- HONK = {
13
- InputKeyMapUtils.createKeyMap(INPUT_MODES.KeyboardAndMouse, { Enum.KeyCode.H });
14
- InputKeyMapUtils.createKeyMap(INPUT_MODES.Gamepads, { Enum.KeyCode.DPadUp });
15
- InputKeyMapUtils.createKeyMap(INPUT_MODES.Touch, { InputKeyMapUtils.createSlottedTouchButton("primary2") });
16
- };
17
- BOOST = {
18
- InputKeyMapUtils.createKeyMap(INPUT_MODES.KeyboardAndMouse, { Enum.KeyCode.LeftControl });
19
- InputKeyMapUtils.createKeyMap(INPUT_MODES.Gamepads, { Enum.KeyCode.ButtonX });
20
- InputKeyMapUtils.createKeyMap(INPUT_MODES.Touch, { InputKeyMapUtils.createSlottedTouchButton("primary4") });
21
- };
22
- }
23
- ```
24
-
25
- Then, we can use these input maps in a variety of services, including [ScoredActionService] or
26
- just binding directly to [ContextActionService].
27
-
28
- ```lua
29
- local inputKeyMapList = inputMap.JUMP
30
-
31
- ContextActionService:BindActionAtPriority(
32
- "MyAction",
33
- function(_actionName, userInputState, inputObject)
34
- print("Process input", inputObject)
35
- end,
36
- InputKeyMapUtils.isRobloxTouchButton(inputKeyMapList),
37
- Enum.ContextActionPriority.High.Value,
38
- unpack(InputKeyMapUtils.getInputTypesForActionBinding(inputKeyMapList)))
39
- ```
40
-
41
- @class InputKeyMapUtils
42
- ]=]
43
-
44
- local require = require(script.Parent.loader).load(script)
45
-
46
- local Set = require("Set")
47
- local Table = require("Table")
48
-
49
- local InputKeyMapUtils = {}
50
-
51
- --[=[
52
- A valid input type that can be represented here.
53
- @type InputType KeyCode | UserInputType | SlottedTouchButton | "TouchButton" | "Tap" | any
54
- @within InputKeyMapUtils
55
- ]=]
56
-
57
- --[=[
58
- A grouping of input types for a specific input mode to use.
59
-
60
- @interface InputKeyMap
61
- .inputMode InputMode
62
- .inputTypes { InputType }
63
- @within InputKeyMapUtils
64
- ]=]
65
-
66
- --[=[
67
- A mapping of input keys to maps
68
- @type InputKeyMapList { InputKeyMap }
69
- @within InputKeyMapUtils
70
- ]=]
71
-
72
- --[=[
73
- Should be called "createInputKeyMap". Creates a new InputKeyMap.
74
-
75
- @param inputMode InputMode
76
- @param inputTypes { InputType }
77
- @return InputKeyMap
78
- ]=]
79
- function InputKeyMapUtils.createKeyMap(inputMode, inputTypes)
80
- assert(type(inputMode) == "table", "Bad inputMode")
81
- assert(type(inputTypes) == "table", "Bad inputTypes")
82
-
83
- return Table.readonly({
84
- inputMode = inputMode;
85
- inputTypes = inputTypes;
86
- })
87
- end
88
-
89
- --[=[
90
- @param inputKeyMapList InputKeyMapList
91
- @return { KeyCode | UserInputType }
92
- ]=]
93
- function InputKeyMapUtils.getInputTypesSetForActionBinding(inputKeyMapList)
94
- return Set.fromList(InputKeyMapUtils.getInputTypesForActionBinding(inputKeyMapList))
95
- end
96
-
97
- --[=[
98
- Converts keymap into ContextActionService friendly types
99
- @param inputKeyMapList InputKeyMapList
100
- @return { KeyCode | UserInputType }
101
- ]=]
102
- function InputKeyMapUtils.getInputTypesForActionBinding(inputKeyMapList)
103
- assert(type(inputKeyMapList) == "table", "inputKeyMapList must be a table")
104
- local types = {}
105
-
106
- for _, inputKeyMap in pairs(inputKeyMapList) do
107
- assert(inputKeyMap.inputMode, "Bad inputKeyMap.inputMode")
108
- assert(inputKeyMap.inputTypes, "Bad inputKeyMap.inputTypes")
109
-
110
- for _, _type in pairs(inputKeyMap.inputTypes) do
111
- if typeof(_type) == "EnumItem" then
112
- table.insert(types, _type)
113
- end
114
- end
115
- end
116
-
117
- return types
118
- end
119
-
120
- --[=[
121
- Given an inputMode, gets the relevant lists available
122
- @param inputKeyMapList InputKeyMapList
123
- @param inputMode InputMode
124
- @return { InputKeyMap }
125
- ]=]
126
- function InputKeyMapUtils.getInputTypeListForMode(inputKeyMapList, inputMode)
127
- assert(type(inputKeyMapList) == "table", "inputKeyMapList must be a table")
128
-
129
- local results = {}
130
- local seen = {}
131
-
132
- for _, inputKeyMap in pairs(inputKeyMapList) do
133
- if inputKeyMap.inputMode == inputMode then
134
- for _, inputType in pairs(inputKeyMap.inputTypes) do
135
- if not seen then
136
- seen[inputType] = true
137
- table.insert(results, inputType)
138
- end
139
- end
140
- end
141
- end
142
-
143
- return results
144
- end
145
-
146
- --[=[
147
- Gets a set of input types for a given mode from the list.
148
-
149
- @param inputKeyMapList InputKeyMapList
150
- @param inputMode InputMode
151
- @return { [InputType] = true }
152
- ]=]
153
- function InputKeyMapUtils.getInputTypeSetForMode(inputKeyMapList, inputMode)
154
- assert(type(inputKeyMapList) == "table", "inputKeyMapList must be a table")
155
-
156
- local results = {}
157
-
158
- for _, inputKeyMap in pairs(inputKeyMapList) do
159
- if inputKeyMap.inputMode == inputMode then
160
- for _, inputType in pairs(inputKeyMap.inputTypes) do
161
- results[inputType] = true
162
- end
163
- end
164
- end
165
-
166
- return results
167
- end
168
-
169
- --[=[
170
- Retrieves the set of input modes for a given list.
171
-
172
- @param inputKeyMapList InputKeyMapList
173
- @return { InputMode }
174
- ]=]
175
- function InputKeyMapUtils.getInputModes(inputKeyMapList)
176
- assert(type(inputKeyMapList) == "table", "inputKeyMapList must be a table")
177
-
178
- local modes = {}
179
- for _, inputKeyMap in pairs(inputKeyMapList) do
180
- local mode = assert(inputKeyMap.inputMode, "Bad inputKeyMap.inputMode")
181
- table.insert(modes, mode)
182
- end
183
-
184
- return modes
185
- end
186
-
187
- --[=[
188
- Internal data representing a slotted touch button
189
- @interface SlottedTouchButtonData
190
- .slotId string
191
- .inputMode InputMode
192
- @within InputKeyMapUtils
193
- ]=]
194
-
195
- --[=[
196
- Gets slotted touch button data for an inputKeyMapList
197
-
198
- @param inputKeyMapList InputKeyMapList
199
- @return { SlottedTouchButtonData }
200
- ]=]
201
- function InputKeyMapUtils.getSlottedTouchButtonData(inputKeyMapList)
202
- local slottedTouchButtons = {}
203
-
204
- for _, inputKeyMap in pairs(inputKeyMapList) do
205
- assert(inputKeyMap.inputMode, "Bad inputKeyMap.inputMode")
206
- assert(inputKeyMap.inputTypes, "Bad inputKeyMap.inputTypes")
207
-
208
- for _, touchButtonData in pairs(inputKeyMap.inputTypes) do
209
- if InputKeyMapUtils.isSlottedTouchButton(touchButtonData) then
210
- table.insert(slottedTouchButtons, {
211
- slotId = touchButtonData.slotId;
212
- inputMode = inputKeyMap.inputMode;
213
- })
214
- end
215
- end
216
- end
217
-
218
- return slottedTouchButtons
219
- end
220
-
221
- --[=[
222
- Returns whether an inputType is a SlottedTouchButton type
223
-
224
- @param inputType any
225
- @return boolean
226
- ]=]
227
- function InputKeyMapUtils.isSlottedTouchButton(inputType)
228
- return type(inputType) == "table" and inputType.type == "SlottedTouchButton"
229
- end
230
-
231
- --[=[
232
- A touch button that goes into a specific slot. This ensures
233
- consistent slot positions.
234
-
235
- @interface SlottedTouchButton
236
- .type "SlottedTouchButton"
237
- .slotId string
238
- @within InputKeyMapUtils
239
- ]=]
240
-
241
- --[=[
242
- Touch buttons should always show up in the same position
243
- We use the SlotId to determine which slot we should put
244
- these buttons in.
245
-
246
- @param slotId string
247
- @return SlottedTouchButton
248
- ]=]
249
- function InputKeyMapUtils.createSlottedTouchButton(slotId)
250
- assert(slotId == "primary1"
251
- or slotId == "primary2"
252
- or slotId == "primary3"
253
- or slotId == "primary4"
254
- or slotId == "touchpad1", "Bad slotId")
255
-
256
- return {
257
- type = "SlottedTouchButton";
258
- slotId = slotId;
259
- }
260
- end
261
-
262
- --[=[
263
- Computes a unique id for an inputType which can be used
264
- in a set to deduplicate/compare the objects. Used to know
265
- when to exclude different types from each other.
266
-
267
- @param inputType InputType
268
- @return any
269
- ]=]
270
- function InputKeyMapUtils.getUniqueKeyForInputType(inputType)
271
- if InputKeyMapUtils.isSlottedTouchButton(inputType) then
272
- return inputType.slotId
273
- else
274
- return inputType
275
- end
276
- end
277
-
278
- --[=[
279
- Only returns true if we're a Roblox touch button
280
- @param inputKeyMapList InputKeyMapList
281
- @return boolean
282
- ]=]
283
- function InputKeyMapUtils.isRobloxTouchButton(inputKeyMapList)
284
- for _, inputKeyMap in pairs(inputKeyMapList) do
285
- assert(inputKeyMap.inputMode, "Bad inputKeyMap.inputMode")
286
- assert(inputKeyMap.inputTypes, "Bad inputKeyMap.inputTypes")
287
-
288
- for _, _type in pairs(inputKeyMap.inputTypes) do
289
- if _type == "TouchButton" then
290
- return true
291
- end
292
- end
293
- end
294
-
295
- return false
296
- end
297
-
298
- --[=[
299
- Whether this input type is a tap in the world input (for touched events)
300
- @param inputKeyMapList InputKeyMapList
301
- @return boolean
302
- ]=]
303
- function InputKeyMapUtils.isTapInWorld(inputKeyMapList)
304
- assert(type(inputKeyMapList) == "table", "inputKeyMap must be a table")
305
-
306
- for _, inputKeyMap in pairs(inputKeyMapList) do
307
- assert(inputKeyMap.inputMode, "Bad inputKeyMap.inputMode")
308
- assert(inputKeyMap.inputTypes, "Bad inputKeyMap.inputTypes")
309
-
310
- for _, _type in pairs(inputKeyMap.inputTypes) do
311
- if _type == "Tap" then
312
- return true
313
- end
314
- end
315
- end
316
-
317
- return false
318
- end
319
-
320
- return InputKeyMapUtils