@quenty/inputmode 5.2.0 → 6.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,6 +3,14 @@
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
+ # [6.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/inputmode@5.2.0...@quenty/inputmode@6.0.0) (2022-08-14)
7
+
8
+ **Note:** Version bump only for package @quenty/inputmode
9
+
10
+
11
+
12
+
13
+
6
14
  # [5.2.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/inputmode@5.1.0...@quenty/inputmode@5.2.0) (2022-07-31)
7
15
 
8
16
  **Note:** Version bump only for package @quenty/inputmode
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/inputmode",
3
- "version": "5.2.0",
3
+ "version": "6.0.0",
4
4
  "description": "Trace input mode state and trigger changes correctly",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -29,10 +29,10 @@
29
29
  "@quenty/maid": "^2.4.0",
30
30
  "@quenty/signal": "^2.2.0",
31
31
  "@quenty/table": "^3.1.0",
32
- "@quenty/valueobject": "^5.2.0"
32
+ "@quenty/valueobject": "^6.0.0"
33
33
  },
34
34
  "publishConfig": {
35
35
  "access": "public"
36
36
  },
37
- "gitHead": "e31b3a35aa475bb5699a24898a8639e107165b36"
37
+ "gitHead": "dbb62609f980983cc32da90acfef13e30ed41113"
38
38
  }
@@ -1,6 +1,6 @@
1
1
  --[=[
2
2
  Trace input mode state and trigger changes correctly. See [InputModeSelector] for details
3
- on how to select between these. See [INPUT_MODES] for predefined modes.
3
+ on how to select between these. See [InputModeTypeTypes] for predefined modes.
4
4
 
5
5
  @class InputMode
6
6
  ]=]
@@ -26,23 +26,21 @@ InputMode.__index = InputMode
26
26
  InputMode.ClassName = "InputMode"
27
27
 
28
28
  --[=[
29
- Constructs a new InputMode
29
+ Constructs a new InputMode. This inherits data from the name.
30
30
 
31
- @param name string
32
- @param typesAndInputModes { { UserInputType | KeyCode | string | InputMode } }
31
+ @param inputModeType InputModeType
33
32
  @return InputMode
34
33
  ]=]
35
- function InputMode.new(name, typesAndInputModes)
34
+ function InputMode.new(inputModeType)
36
35
  local self = setmetatable({}, InputMode)
37
36
 
37
+ self._inputModeType = assert(inputModeType, "Bad inputModeType")
38
+
38
39
  self._lastEnabled = 0
39
- self._valid = {}
40
40
 
41
- self.Name = name or "Unnamed"
41
+ self.Name = self._inputModeType.Name
42
42
  self.Enabled = Signal.new()
43
43
 
44
- self:_addValidTypesFromTable(typesAndInputModes)
45
-
46
44
  return self
47
45
  end
48
46
 
@@ -63,34 +61,12 @@ function InputMode:GetLastEnabledTime()
63
61
  return self._lastEnabled
64
62
  end
65
63
 
66
- function InputMode:_addValidTypesFromTable(keys)
67
- for _, key in pairs(keys) do
68
- if typeof(key) == "EnumItem" then
69
- self._valid[key] = true
70
- elseif type(key) == "table" then
71
- self:_addInputMode(key)
72
- end
73
- end
74
- end
75
-
76
- function InputMode:_addInputMode(inputMode)
77
- assert(inputMode.ClassName == "InputMode", "bad inputMode")
78
-
79
- for key, _ in pairs(inputMode._valid) do
80
- self._valid[key] = true
81
- end
82
- end
83
-
84
64
  --[=[
85
65
  Returns all keys defining the input mode.
86
66
  @return { UserInputType | KeyCode | string }
87
67
  ]=]
88
68
  function InputMode:GetKeys()
89
- local keys = {}
90
- for key, _ in pairs(self._valid) do
91
- table.insert(keys, key)
92
- end
93
- return keys
69
+ return self._inputModeType:GetKeys()
94
70
  end
95
71
 
96
72
  --[=[
@@ -101,7 +77,7 @@ end
101
77
  function InputMode:IsValid(inputType)
102
78
  assert(inputType, "Must send in inputType")
103
79
 
104
- return self._valid[inputType]
80
+ return self._inputModeType:IsValid(inputType)
105
81
  end
106
82
 
107
83
  --[=[
@@ -117,11 +93,18 @@ end
117
93
  @param inputObject InputObject
118
94
  ]=]
119
95
  function InputMode:Evaluate(inputObject)
120
- if self._valid[inputObject.UserInputType]
121
- or self._valid[inputObject.KeyCode] then
96
+ if self._inputModeType:IsValid(inputObject.UserInputType)
97
+ or self._inputModeType:IsValid(inputObject.KeyCode) then
122
98
 
123
99
  self:Enable()
124
100
  end
125
101
  end
126
102
 
103
+ --[=[
104
+ Cleans up the input mode
105
+ ]=]
106
+ function InputMode:Destroy()
107
+ self.Enabled:Destroy()
108
+ end
109
+
127
110
  return InputMode
@@ -1,6 +1,5 @@
1
1
  --[=[
2
- Process inputs by evaluating inputModes. Typically not used directly, but rather, just
3
- use modes from INPUT_MODES.
2
+ Process inputs by evaluating inputModes. Helper object..
4
3
 
5
4
  @class InputModeProcessor
6
5
  ]=]
@@ -11,7 +10,7 @@ InputModeProcessor.ClassName = InputModeProcessor
11
10
 
12
11
  --[=[
13
12
  Construtcs a new inputModeProcessor
14
- @param inputModes { InputMode }
13
+ @param inputModes { InputMode }?
15
14
  @return InputModeProcessor
16
15
  ]=]
17
16
  function InputModeProcessor.new(inputModes)
@@ -19,13 +18,19 @@ function InputModeProcessor.new(inputModes)
19
18
 
20
19
  self._inputModes = {}
21
20
 
22
- for _, state in pairs(inputModes) do
23
- self._inputModes[#self._inputModes+1] = state
21
+ if inputModes then
22
+ for _, inputMode in pairs(inputModes) do
23
+ self:AddInputMode(inputMode)
24
+ end
24
25
  end
25
26
 
26
27
  return self
27
28
  end
28
29
 
30
+ function InputModeProcessor:AddInputMode(inputMode)
31
+ table.insert(self._inputModes, inputMode)
32
+ end
33
+
29
34
  --[=[
30
35
  Gets all input mode inputModes being used
31
36
  @return { InputMode }
@@ -0,0 +1,115 @@
1
+ --[=[
2
+ Centralized
3
+ @class InputModeServiceClient
4
+ ]=]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local UserInputService = game:GetService("UserInputService")
9
+ local GuiService = game:GetService("GuiService")
10
+
11
+ local InputModeType = require("InputModeType")
12
+ local Maid = require("Maid")
13
+ local InputModeProcessor = require("InputModeProcessor")
14
+ local InputModeTypes = require("InputModeTypes")
15
+ local InputMode = require("InputMode")
16
+
17
+ local THUMBSTICK_DEADZONE = 0.14
18
+
19
+ local InputModeServiceClient = {}
20
+ InputModeServiceClient.ServiceName = "InputModeServiceClient"
21
+
22
+ function InputModeServiceClient:Init(serviceBag)
23
+ assert(not self._serviceBag, "Already initialized")
24
+ self._serviceBag = assert(serviceBag, "No serviceBag")
25
+
26
+ self._maid = Maid.new()
27
+ self._inputModes = {}
28
+
29
+ self._inputModeProcessor = InputModeProcessor.new()
30
+
31
+ -- order semi-matters. general should come first, to non-specific. that way, specific stuff has
32
+ -- priority over non-specific input modes.
33
+ self:GetInputMode(InputModeTypes.KeyboardAndMouse);
34
+ self:GetInputMode(InputModeTypes.Gamepads);
35
+ self:GetInputMode(InputModeTypes.Keyboard);
36
+ self:GetInputMode(InputModeTypes.Touch);
37
+ self:GetInputMode(InputModeTypes.Mouse);
38
+ self:GetInputMode(InputModeTypes.ArrowKeys);
39
+ self:GetInputMode(InputModeTypes.Keypad);
40
+ self:GetInputMode(InputModeTypes.WASD);
41
+ self:GetInputMode(InputModeTypes.DPad);
42
+ -- Don't add InputModeTypes.Thumbsticks, we handle it seperately
43
+
44
+ self:_triggerEnabled()
45
+ self:_bindProcessor()
46
+ end
47
+
48
+ function InputModeServiceClient:GetInputMode(inputModeType)
49
+ assert(InputModeType.isInputModeType(inputModeType), "Bad inputModeType")
50
+
51
+ if self._inputModes[inputModeType] then
52
+ return self._inputModes[inputModeType]
53
+ end
54
+
55
+ local inputMode = InputMode.new(inputModeType)
56
+ self._maid:GiveTask(inputMode)
57
+
58
+ self._inputModes[inputModeType] = inputMode
59
+ return inputMode
60
+ end
61
+
62
+ function InputModeServiceClient:_triggerEnabled()
63
+ if UserInputService.MouseEnabled then
64
+ self:GetInputMode(InputModeTypes.Mouse):Enable()
65
+ end
66
+ if UserInputService.TouchEnabled then
67
+ self:GetInputMode(InputModeTypes.Touch):Enable()
68
+ end
69
+ if UserInputService.KeyboardEnabled then
70
+ self:GetInputMode(InputModeTypes.Keyboard):Enable()
71
+ end
72
+ if UserInputService.KeyboardEnabled and UserInputService.MouseEnabled then
73
+ self:GetInputMode(InputModeTypes.KeyboardAndMouse):Enable()
74
+ end
75
+ if UserInputService.GamepadEnabled
76
+ or #UserInputService:GetConnectedGamepads() > 0
77
+ or GuiService:IsTenFootInterface() then
78
+ self:GetInputMode(InputModeTypes.Gamepads):Enable()
79
+ end
80
+ end
81
+
82
+ function InputModeServiceClient:_bindProcessor()
83
+ self._maid:GiveTask(UserInputService.InputBegan:Connect(function(inputObject)
84
+ self._inputModeProcessor:Evaluate(inputObject)
85
+ end))
86
+ self._maid:GiveTask(UserInputService.InputEnded:Connect(function(inputObject)
87
+ self._inputModeProcessor:Evaluate(inputObject)
88
+ end))
89
+ self._maid:GiveTask(UserInputService.InputChanged:Connect(function(inputObject)
90
+ if inputObject.KeyCode == Enum.KeyCode.Thumbstick1
91
+ or inputObject.KeyCode == Enum.KeyCode.Thumbstick2 then
92
+
93
+ if inputObject.Position.magnitude > THUMBSTICK_DEADZONE then
94
+ self._inputModeProcessor:Evaluate(inputObject)
95
+ self:GetInputMode(InputModeTypes.Thumbsticks):Enable()
96
+ end
97
+ else
98
+ self._inputModeProcessor:Evaluate(inputObject)
99
+ end
100
+ end))
101
+
102
+ self._maid:GiveTask(UserInputService.GamepadConnected:Connect(function(_)
103
+ self:GetInputMode(InputModeTypes.Gamepads):Enable()
104
+ end))
105
+
106
+ self._maid:GiveTask(UserInputService.GamepadDisconnected:Connect(function(_)
107
+ self:_triggerEnabled()
108
+ end))
109
+ end
110
+
111
+ function InputModeServiceClient:Destroy()
112
+ self._maid:DoCleaning()
113
+ end
114
+
115
+ return InputModeServiceClient
@@ -0,0 +1,242 @@
1
+ --[=[
2
+ Selects the most recent input mode and attempts to identify the best state from it.
3
+ @class InputModeTypeSelector
4
+ ]=]
5
+
6
+ local require = require(script.Parent.loader).load(script)
7
+
8
+ local InputModeTypes = require("InputModeTypes")
9
+ local Maid = require("Maid")
10
+ local ValueObject = require("ValueObject")
11
+ local InputModeServiceClient = require("InputModeServiceClient")
12
+ local ServiceBag = require("ServiceBag")
13
+
14
+ local InputModeTypeSelector = {}
15
+ InputModeTypeSelector.ClassName = "InputModeTypeSelector"
16
+ InputModeTypeSelector.DEFAULT_MODE_TYPES = {
17
+ InputModeTypes.Gamepads,
18
+ InputModeTypes.Keyboard,
19
+ InputModeTypes.Touch
20
+ }
21
+
22
+ --[=[
23
+ Constructs a new InputModeTypeSelector
24
+
25
+ @param serviceBag ServiceBag
26
+ @param inputModesTypes { InputModeType }
27
+ @return InputModeTypeSelector
28
+ ]=]
29
+ function InputModeTypeSelector.new(serviceBag, inputModesTypes)
30
+ local self = setmetatable({}, InputModeTypeSelector)
31
+
32
+ assert(ServiceBag.isServiceBag(serviceBag), "Bad serviceBag")
33
+
34
+ self._serviceBag = assert(serviceBag, "No serviceBag")
35
+
36
+ self._inputModeServiceClient = self._serviceBag:GetService(InputModeServiceClient)
37
+
38
+ self._maid = Maid.new()
39
+
40
+ -- keep this ordered so we are always stable in selection.
41
+ self._inputModeTypeList = {}
42
+
43
+ self._activeModeType = ValueObject.new()
44
+ self._maid:GiveTask(self._activeModeType)
45
+
46
+ --[=[
47
+ Event that fires whenever the active mode changes.
48
+ @prop Changed Signal<InputModeType, InputModeType> -- newMode, oldMode
49
+ @within InputModeTypeSelector
50
+ ]=]
51
+ self.Changed = self._activeModeType.Changed
52
+
53
+ for _, inputModeType in pairs(inputModesTypes or InputModeTypeSelector.DEFAULT_MODE_TYPES) do
54
+ self:AddInputModeType(inputModeType)
55
+ end
56
+
57
+ return self
58
+ end
59
+
60
+ --[=[
61
+ Constructs a new InputModeTypeSelector
62
+
63
+ @param serviceBag ServiceBag
64
+ @param observeInputModesBrio Observable<Brio<InputModeType>>
65
+ @return InputModeTypeSelector
66
+ ]=]
67
+ function InputModeTypeSelector.fromObservableBrio(serviceBag, observeInputModesBrio)
68
+ local selector = InputModeTypeSelector.new(serviceBag, {})
69
+
70
+ selector._maid:GiveTask(observeInputModesBrio:Subscribe(function(brio)
71
+ if brio:IsDead() then
72
+ return
73
+ end
74
+
75
+ local inputModeType = brio:GetValue()
76
+ local maid = brio:ToMaid()
77
+ selector:AddInputModeType(inputModeType)
78
+
79
+ maid:GiveTask(function()
80
+ if selector.Destroy then
81
+ selector:RemoveInputModeType(inputModeType)
82
+ end
83
+ end)
84
+ end))
85
+
86
+ return selector
87
+ end
88
+
89
+ --[=[
90
+ Returns the current active mode
91
+ @return InputModeType
92
+ ]=]
93
+ function InputModeTypeSelector:GetActiveInputType()
94
+ return rawget(self, "_activeModeType").Value
95
+ end
96
+
97
+ --[=[
98
+ Observes the current active mode
99
+ @return Observable<InputModeType>
100
+ ]=]
101
+ function InputModeTypeSelector:ObserveActiveInputType()
102
+ return rawget(self, "_activeModeType"):Observe()
103
+ end
104
+
105
+ --[=[
106
+ The current active input mode
107
+ @prop Value InputModeType?
108
+ @within InputModeTypeSelector
109
+ ]=]
110
+ function InputModeTypeSelector:__index(index)
111
+ if index == "Value" then
112
+ return rawget(self, "_activeModeType").Value
113
+ elseif InputModeTypeSelector[index] then
114
+ return InputModeTypeSelector[index]
115
+ else
116
+ local value = rawget(self, index)
117
+ if value then
118
+ return value
119
+ else
120
+ error(("[InputModeTypeSelector] - Bad index '%s'"):format(tostring(index)))
121
+ end
122
+ end
123
+ end
124
+
125
+ --[=[
126
+ Binds the updateBindFunction to the mode selector
127
+
128
+ ```lua
129
+ local inputModeTypeSelector = InputModeTypeSelector.new({
130
+ InputModeTypes.Mouse;
131
+ InputModeTypes.Touch;
132
+ })
133
+
134
+ inputModeTypeSelector:Bind(function(inputModeType)
135
+ if inputModeType == InputModeTypes.Mouse then
136
+ print("Show mouse input hints")
137
+ elseif inputModeType == InputModeTypes.Touch then
138
+ print("Show touch input hints")
139
+ else
140
+ -- Unknown input mode
141
+ warn("Unknown input mode") -- should not occur
142
+ end
143
+ end)
144
+ ```
145
+
146
+ @param updateBindFunction (newMode: InputModeType, modeMaid: Maid) -> ()
147
+ @return InputModeTypeSelector
148
+ ]=]
149
+ function InputModeTypeSelector:Bind(updateBindFunction)
150
+ local maid = Maid.new()
151
+ self._maid[updateBindFunction] = maid
152
+
153
+ local function onChange(newMode, _)
154
+ maid._modeMaid = nil
155
+
156
+ if newMode then
157
+ local modeMaid = Maid.new()
158
+ maid._modeMaid = modeMaid
159
+
160
+ if newMode then
161
+ updateBindFunction(newMode, modeMaid)
162
+ end
163
+ end
164
+ end
165
+
166
+ maid:GiveTask(self._activeModeType.Changed:Connect(onChange))
167
+ onChange(self._activeModeType.Value, nil)
168
+
169
+ return self
170
+ end
171
+
172
+ --[=[
173
+ Removes the input mode
174
+ @param inputModeType InputModeType
175
+ ]=]
176
+ function InputModeTypeSelector:RemoveInputModeType(inputModeType)
177
+ if not self._maid[inputModeType] then
178
+ return
179
+ end
180
+
181
+ local index = table.find(self._inputModeTypeList, inputModeType)
182
+ if index then
183
+ table.remove(self._inputModeTypeList, index)
184
+ else
185
+ warn("[InputModeTypeSelector] - Failed to find inputModeType")
186
+ end
187
+
188
+ self._maid[inputModeType] = nil
189
+
190
+ if self._activeModeType.Value == inputModeType then
191
+ self:_pickNewInputMode()
192
+ end
193
+ end
194
+
195
+ --[=[
196
+ Adds a new input mode
197
+ @param inputModeType InputModeType
198
+ ]=]
199
+ function InputModeTypeSelector:AddInputModeType(inputModeType)
200
+ if self._maid[inputModeType] then
201
+ return
202
+ end
203
+
204
+ table.insert(self._inputModeTypeList, inputModeType)
205
+ local inputMode = self._inputModeServiceClient:GetInputMode(inputModeType)
206
+ self._maid[inputModeType] = inputMode.Enabled:Connect(function()
207
+ self._activeModeType.Value = inputModeType
208
+ end)
209
+
210
+ if not self._activeModeType.Value
211
+ or inputMode:GetLastEnabledTime() > self._inputModeServiceClient:GetInputMode(self._activeModeType.Value):GetLastEnabledTime() then
212
+ self._activeModeType.Value = inputModeType
213
+ end
214
+ end
215
+
216
+ function InputModeTypeSelector:_pickNewInputMode()
217
+ local bestEnabledTime = -math.huge
218
+ local bestModeType
219
+ for _, inputModeType in pairs(self._inputModeTypeList) do
220
+ local enableTime = self._inputModeServiceClient:GetInputMode(inputModeType):GetLastEnabledTime()
221
+ if enableTime >= bestEnabledTime then
222
+ bestEnabledTime = enableTime
223
+ bestModeType = inputModeType
224
+ end
225
+ end
226
+
227
+ self._activeModeType.Value = bestModeType
228
+ end
229
+
230
+ --[=[
231
+ Cleans up the input mode selector.
232
+
233
+ :::info
234
+ This should be called whenever the mode selector is done being used.
235
+ :::
236
+ ]=]
237
+ function InputModeTypeSelector:Destroy()
238
+ self._maid:DoCleaning()
239
+ setmetatable(self, nil)
240
+ end
241
+
242
+ return InputModeTypeSelector
@@ -0,0 +1,81 @@
1
+ --[=[
2
+ Type specification for input modes, which is static. Separated out from InputMode which is dynamic.
3
+
4
+ @class InputModeType
5
+ ]=]
6
+
7
+ local InputModeType = {}
8
+ InputModeType.ClassName = "InputModeType"
9
+ InputModeType.__index = InputModeType
10
+
11
+ --[=[
12
+ Constructs a new InputModeType
13
+
14
+ @param name string
15
+ @param typesAndInputModes { { UserInputType | KeyCode | string | InputMode } }
16
+ @return InputMode
17
+ ]=]
18
+ function InputModeType.new(name, typesAndInputModes)
19
+ local self = setmetatable({}, InputModeType)
20
+
21
+ self._valid = {}
22
+ self.Name = name or "Unnamed"
23
+
24
+ self:_addValidTypesFromTable(typesAndInputModes)
25
+
26
+ return self
27
+ end
28
+
29
+ --[=[
30
+ Returns true if a given value is an InputModeType
31
+ @param value any
32
+ @return boolean
33
+ ]=]
34
+ function InputModeType.isInputModeType(value)
35
+ return type(value) == "table" and getmetatable(value) == InputModeType
36
+ end
37
+
38
+ --[=[
39
+ Checks the validity of the inputType
40
+ @param inputType { UserInputType | KeyCode | string }
41
+ @return boolean
42
+ ]=]
43
+ function InputModeType:IsValid(inputType)
44
+ assert(inputType, "Must send in inputType")
45
+
46
+ return self._valid[inputType]
47
+ end
48
+
49
+ --[=[
50
+ Returns all keys defining the input mode.
51
+ @return { UserInputType | KeyCode | string }
52
+ ]=]
53
+ function InputModeType:GetKeys()
54
+ local keys = {}
55
+ for key, _ in pairs(self._valid) do
56
+ table.insert(keys, key)
57
+ end
58
+ return keys
59
+ end
60
+
61
+ function InputModeType:_addValidTypesFromTable(keys)
62
+ for _, key in pairs(keys) do
63
+ if typeof(key) == "EnumItem" then
64
+ self._valid[key] = true
65
+ elseif InputModeType.isInputModeType(key) then
66
+ self:_addInputModeType(key)
67
+ end
68
+ end
69
+ end
70
+
71
+ function InputModeType:_addInputModeType(inputModeType)
72
+ assert(InputModeType.isInputModeType(inputModeType), "Bad inputModeType")
73
+
74
+ for key, _ in pairs(inputModeType._valid) do
75
+ self._valid[key] = true
76
+ end
77
+ end
78
+
79
+
80
+
81
+ return InputModeType
@@ -1,31 +1,22 @@
1
1
  --[=[
2
- Holds input states for Keyboard, Mouse, et cetera. Mostly useful for providing UI input hints to the user by
3
- identifying the most recent input state provided. See [InputMode] for more details, and [InputModeSelector] for
4
- how to select between several modes.
5
-
6
- @class INPUT_MODES
2
+ Holds all the input mode type configuration, accessible on both the server and the client for keybinding validations.
3
+ @class InputModeTypes
7
4
  ]=]
8
5
 
9
- local UserInputService = game:GetService("UserInputService")
10
- local GuiService = game:GetService("GuiService")
11
-
12
6
  local require = require(script.Parent.loader).load(script)
13
7
 
14
- local InputMode = require("InputMode")
15
- local InputModeProcessor = require("InputModeProcessor")
16
8
  local Table = require("Table")
9
+ local InputModeType = require("InputModeType")
17
10
 
18
- local INPUT_MODES = {
19
- THUMBSTICK_DEADZONE = 0.14
20
- }
11
+ local InputModeTypes = {}
21
12
 
22
13
  --[=[
23
14
  Input from a keypad
24
- @prop Keypad InputMode
15
+ @prop Keypad InputModeType
25
16
  @readonly
26
- @within INPUT_MODES
17
+ @within InputModeTypes
27
18
  ]=]
28
- INPUT_MODES.Keypad = InputMode.new("Keypad", {
19
+ InputModeTypes.Keypad = InputModeType.new("Keypad", {
29
20
  Enum.KeyCode.KeypadZero;
30
21
  Enum.KeyCode.KeypadOne;
31
22
  Enum.KeyCode.KeypadTwo;
@@ -47,15 +38,15 @@ INPUT_MODES.Keypad = InputMode.new("Keypad", {
47
38
 
48
39
  --[=[
49
40
  Input from a keyboard
50
- @prop Keyboard InputMode
41
+ @prop Keyboard InputModeType
51
42
  @readonly
52
- @within INPUT_MODES
43
+ @within InputModeTypes
53
44
  ]=]
54
- INPUT_MODES.Keyboard = InputMode.new("Keyboard", {
45
+ InputModeTypes.Keyboard = InputModeType.new("Keyboard", {
55
46
  Enum.UserInputType.Keyboard;
56
47
 
57
48
  -- Other input modes
58
- INPUT_MODES.Keypad;
49
+ InputModeTypes.Keypad;
59
50
 
60
51
  -- Valid KeyCodes for input binding
61
52
  Enum.KeyCode.Backspace;
@@ -184,11 +175,11 @@ INPUT_MODES.Keyboard = InputMode.new("Keyboard", {
184
175
 
185
176
  --[=[
186
177
  Input involving arrow keys!
187
- @prop ArrowKeys InputMode
178
+ @prop ArrowKeys InputModeType
188
179
  @readonly
189
- @within INPUT_MODES
180
+ @within InputModeTypes
190
181
  ]=]
191
- INPUT_MODES.ArrowKeys = InputMode.new("ArrowKeys", {
182
+ InputModeTypes.ArrowKeys = InputModeType.new("ArrowKeys", {
192
183
  Enum.KeyCode.Left;
193
184
  Enum.KeyCode.Right;
194
185
  Enum.KeyCode.Up;
@@ -197,11 +188,11 @@ INPUT_MODES.ArrowKeys = InputMode.new("ArrowKeys", {
197
188
 
198
189
  --[=[
199
190
  Input involving WASD
200
- @prop WASD InputMode
191
+ @prop WASD InputModeType
201
192
  @readonly
202
- @within INPUT_MODES
193
+ @within InputModeTypes
203
194
  ]=]
204
- INPUT_MODES.WASD = InputMode.new("WASD", {
195
+ InputModeTypes.WASD = InputModeType.new("WASD", {
205
196
  Enum.KeyCode.W;
206
197
  Enum.KeyCode.A;
207
198
  Enum.KeyCode.S;
@@ -210,11 +201,11 @@ INPUT_MODES.WASD = InputMode.new("WASD", {
210
201
 
211
202
  --[=[
212
203
  Input involving the mouse
213
- @prop Mouse InputMode
204
+ @prop Mouse InputModeType
214
205
  @readonly
215
- @within INPUT_MODES
206
+ @within InputModeTypes
216
207
  ]=]
217
- INPUT_MODES.Mouse = InputMode.new("Mouse", {
208
+ InputModeTypes.Mouse = InputModeType.new("Mouse", {
218
209
  Enum.UserInputType.MouseButton1;
219
210
  Enum.UserInputType.MouseButton2;
220
211
  Enum.UserInputType.MouseButton3;
@@ -224,31 +215,31 @@ INPUT_MODES.Mouse = InputMode.new("Mouse", {
224
215
 
225
216
  --[=[
226
217
  Input involving the keyboard OR mouse.
227
- @prop KeyboardAndMoues InputMode
218
+ @prop KeyboardAndMoues InputModeType
228
219
  @readonly
229
- @within INPUT_MODES
220
+ @within InputModeTypes
230
221
  ]=]
231
- INPUT_MODES.KeyboardAndMouse = InputMode.new("KeyboardAndMouse", {
232
- INPUT_MODES.Mouse;
233
- INPUT_MODES.Keyboard;
222
+ InputModeTypes.KeyboardAndMouse = InputModeType.new("KeyboardAndMouse", {
223
+ InputModeTypes.Mouse;
224
+ InputModeTypes.Keyboard;
234
225
  })
235
226
 
236
227
  --[=[
237
228
  Input involving touch input.
238
- @prop Touch InputMode
229
+ @prop Touch InputModeType
239
230
  @readonly
240
- @within INPUT_MODES
231
+ @within InputModeTypes
241
232
  ]=]
242
- INPUT_MODES.Touch = InputMode.new("Touch", {
233
+ InputModeTypes.Touch = InputModeType.new("Touch", {
243
234
  Enum.UserInputType.Touch;
244
235
  })
245
236
 
246
237
  --[=[
247
- @prop DPad InputMode
238
+ @prop DPad InputModeType
248
239
  @readonly
249
- @within INPUT_MODES
240
+ @within InputModeTypes
250
241
  ]=]
251
- INPUT_MODES.DPad = InputMode.new("DPad", {
242
+ InputModeTypes.DPad = InputModeType.new("DPad", {
252
243
  Enum.KeyCode.DPadLeft;
253
244
  Enum.KeyCode.DPadRight;
254
245
  Enum.KeyCode.DPadUp;
@@ -257,22 +248,22 @@ INPUT_MODES.DPad = InputMode.new("DPad", {
257
248
 
258
249
  --[=[
259
250
  Input involved thumbsticks.
260
- @prop Thumbsticks InputMode
251
+ @prop Thumbsticks InputModeType
261
252
  @readonly
262
- @within INPUT_MODES
253
+ @within InputModeTypes
263
254
  ]=]
264
- INPUT_MODES.Thumbsticks = InputMode.new("Thumbsticks", {
255
+ InputModeTypes.Thumbsticks = InputModeType.new("Thumbsticks", {
265
256
  Enum.KeyCode.Thumbstick1;
266
257
  Enum.KeyCode.Thumbstick2;
267
258
  })
268
259
 
269
260
  --[=[
270
261
  Input involving gamepads
271
- @prop Gamepads InputMode
262
+ @prop Gamepads InputModeType
272
263
  @readonly
273
- @within INPUT_MODES
264
+ @within InputModeTypes
274
265
  ]=]
275
- INPUT_MODES.Gamepads = InputMode.new("Gamepads", {
266
+ InputModeTypes.Gamepads = InputModeType.new("Gamepads", {
276
267
  Enum.UserInputType.Gamepad1;
277
268
  Enum.UserInputType.Gamepad2;
278
269
  Enum.UserInputType.Gamepad3;
@@ -301,69 +292,4 @@ INPUT_MODES.Gamepads = InputMode.new("Gamepads", {
301
292
  Enum.KeyCode.DPadDown;
302
293
  })
303
294
 
304
- local function triggerEnabled()
305
- if UserInputService.MouseEnabled then
306
- INPUT_MODES.Mouse:Enable()
307
- end
308
- if UserInputService.TouchEnabled then
309
- INPUT_MODES.Touch:Enable()
310
- end
311
- if UserInputService.KeyboardEnabled then
312
- INPUT_MODES.Keyboard:Enable()
313
- end
314
- if UserInputService.KeyboardEnabled and UserInputService.MouseEnabled then
315
- INPUT_MODES.KeyboardAndMouse:Enable()
316
- end
317
- if UserInputService.GamepadEnabled
318
- or #UserInputService:GetConnectedGamepads() > 0
319
- or GuiService:IsTenFootInterface() then
320
- INPUT_MODES.Gamepads:Enable()
321
- end
322
- end
323
-
324
- local function bindProcessor()
325
- local inputProcessor = InputModeProcessor.new({
326
- INPUT_MODES.Keypad;
327
- INPUT_MODES.Keyboard;
328
- INPUT_MODES.Gamepads;
329
- INPUT_MODES.Mouse;
330
- INPUT_MODES.Touch;
331
- INPUT_MODES.ArrowKeys;
332
- INPUT_MODES.WASD;
333
- INPUT_MODES.KeyboardAndMouse;
334
- INPUT_MODES.DPad;
335
- -- Don't add INPUT_MODES.Thumbsticks, we handle it seperately
336
- })
337
-
338
- UserInputService.InputBegan:Connect(function(inputObject)
339
- inputProcessor:Evaluate(inputObject)
340
- end)
341
- UserInputService.InputEnded:Connect(function(inputObject)
342
- inputProcessor:Evaluate(inputObject)
343
- end)
344
- UserInputService.InputChanged:Connect(function(inputObject)
345
- if inputObject.KeyCode == Enum.KeyCode.Thumbstick1
346
- or inputObject.KeyCode == Enum.KeyCode.Thumbstick2 then
347
-
348
- if inputObject.Position.magnitude > INPUT_MODES.THUMBSTICK_DEADZONE then
349
- inputProcessor:Evaluate(inputObject)
350
- INPUT_MODES.Thumbsticks:Enable()
351
- end
352
- else
353
- inputProcessor:Evaluate(inputObject)
354
- end
355
- end)
356
-
357
- UserInputService.GamepadConnected:Connect(function(_)
358
- INPUT_MODES.Gamepads:Enable()
359
- end)
360
-
361
- UserInputService.GamepadDisconnected:Connect(function(_)
362
- triggerEnabled()
363
- end)
364
- end
365
-
366
- bindProcessor()
367
- triggerEnabled()
368
-
369
- return Table.readonly(INPUT_MODES)
295
+ return Table.readonly(InputModeTypes)
@@ -1,229 +0,0 @@
1
- --[=[
2
- Selects the most recent input mode and attempts to identify the best state from it.
3
- @class InputModeSelector
4
- ]=]
5
-
6
- local require = require(script.Parent.loader).load(script)
7
-
8
- local INPUT_MODES = require("INPUT_MODES")
9
- local Maid = require("Maid")
10
- local ValueObject = require("ValueObject")
11
-
12
- local InputModeSelector = {}
13
- InputModeSelector.ClassName = "InputModeSelector"
14
- InputModeSelector.DEFAULT_MODES = {
15
- INPUT_MODES.Gamepads,
16
- INPUT_MODES.Keyboard,
17
- INPUT_MODES.Touch
18
- }
19
-
20
- --[=[
21
- Constructs a new InputModeSelector
22
- @param inputModes { InputMode }
23
- @return InputModeSelector
24
- ]=]
25
- function InputModeSelector.new(inputModes)
26
- local self = setmetatable({}, InputModeSelector)
27
-
28
- self._maid = Maid.new()
29
-
30
- -- keep this ordered so we are always stable in selection.
31
- self._inputModeList = {}
32
-
33
- self._activeMode = ValueObject.new()
34
- self._maid:GiveTask(self._activeMode)
35
-
36
- --[=[
37
- Event that fires whenever the active mode changes.
38
- @prop Changed Signal<InputMode, InputMode> -- newMode, oldMode
39
- @within InputModeSelector
40
- ]=]
41
- self.Changed = self._activeMode.Changed
42
-
43
- for _, inputMode in pairs(inputModes or InputModeSelector.DEFAULT_MODES) do
44
- self:AddInputMode(inputMode)
45
- end
46
-
47
- return self
48
- end
49
-
50
- --[=[
51
- Constructs a new InputModeSelector
52
- @param observeInputModesBrio Observable<Brio<InputMode>>
53
- @return InputModeSelector
54
- ]=]
55
- function InputModeSelector.fromObservableBrio(observeInputModesBrio)
56
- local selector = InputModeSelector.new({})
57
-
58
- selector._maid:GiveTask(observeInputModesBrio:Subscribe(function(brio)
59
- if brio:IsDead() then
60
- return
61
- end
62
-
63
- local inputMode = brio:GetValue()
64
- local maid = brio:ToMaid()
65
- selector:AddInputMode(inputMode)
66
-
67
- maid:GiveTask(function()
68
- if selector.Destroy then
69
- selector:RemoveInputMode(inputMode)
70
- end
71
- end)
72
- end))
73
-
74
- return selector
75
- end
76
-
77
- --[=[
78
- Returns the current active mode
79
- @return InputMode
80
- ]=]
81
- function InputModeSelector:GetActiveMode()
82
- return rawget(self, "_activeMode").Value
83
- end
84
-
85
- --[=[
86
- Observes the current active mode
87
- @return Observable<InputMode>
88
- ]=]
89
- function InputModeSelector:ObserveActiveMode()
90
- return rawget(self, "_activeMode"):Observe()
91
- end
92
-
93
- --[=[
94
- The current active input mode
95
- @prop Value InputMode?
96
- @within InputModeSelector
97
- ]=]
98
- function InputModeSelector:__index(index)
99
- if index == "Value" then
100
- return rawget(self, "_activeMode").Value
101
- elseif InputModeSelector[index] then
102
- return InputModeSelector[index]
103
- else
104
- local value = rawget(self, index)
105
- if value then
106
- return value
107
- else
108
- error(("[InputModeSelector] - Bad index '%s'"):format(tostring(index)))
109
- end
110
- end
111
- end
112
-
113
- --[=[
114
- Binds the updateBindFunction to the mode selector
115
-
116
- ```lua
117
- local inputModeSelector = InputModeSelector.new({
118
- INPUT_MODES.Mouse;
119
- INPUT_MODES.Touch;
120
- })
121
-
122
- inputModeSelector:Bind(function(inputMode)
123
- if inputMode == INPUT_MODES.Mouse then
124
- print("Show mouse input hints")
125
- elseif inputMode == INPUT_MODES.Touch then
126
- print("Show touch input hints")
127
- else
128
- -- Unknown input mode
129
- warn("Unknown input mode") -- should not occur
130
- end
131
- end)
132
- ```
133
-
134
- @param updateBindFunction (newMode: InputMode, modeMaid: Maid) -> ()
135
- @return InputModeSelector
136
- ]=]
137
- function InputModeSelector:Bind(updateBindFunction)
138
- local maid = Maid.new()
139
- self._maid[updateBindFunction] = maid
140
-
141
- local function onChange(newMode, _)
142
- maid._modeMaid = nil
143
-
144
- if newMode then
145
- local modeMaid = Maid.new()
146
- maid._modeMaid = modeMaid
147
-
148
- if newMode then
149
- updateBindFunction(newMode, modeMaid)
150
- end
151
- end
152
- end
153
-
154
- maid:GiveTask(self._activeMode.Changed:Connect(onChange))
155
- onChange(self._activeMode.Value, nil)
156
-
157
- return self
158
- end
159
-
160
- --[=[
161
- Removes the input mode
162
- @param inputMode InputMode
163
- ]=]
164
- function InputModeSelector:RemoveInputMode(inputMode)
165
- if not self._maid[inputMode] then
166
- return
167
- end
168
-
169
- local index = table.find(self._inputModeList, inputMode)
170
- if index then
171
- table.remove(self._inputModeList, index)
172
- else
173
- warn("[InputModeSelector] - Failed to find inputMode")
174
- end
175
-
176
- self._maid[inputMode] = nil
177
-
178
- if self._activeMode.Value == inputMode then
179
- self:_pickNewInputMode()
180
- end
181
- end
182
-
183
- --[=[
184
- Adds a new input mode
185
- @param inputMode InputMode
186
- ]=]
187
- function InputModeSelector:AddInputMode(inputMode)
188
- if self._maid[inputMode] then
189
- return
190
- end
191
-
192
- table.insert(self._inputModeList, inputMode)
193
- self._maid[inputMode] = inputMode.Enabled:Connect(function()
194
- self._activeMode.Value = inputMode
195
- end)
196
-
197
- if not self._activeMode.Value
198
- or inputMode:GetLastEnabledTime() > self._activeMode.Value:GetLastEnabledTime() then
199
- self._activeMode.Value = inputMode
200
- end
201
- end
202
-
203
- function InputModeSelector:_pickNewInputMode()
204
- local bestEnabledTime = -math.huge
205
- local bestMode
206
- for _, inputMode in pairs(self._inputModeList) do
207
- local enableTime = inputMode:GetLastEnabledTime()
208
- if enableTime >= bestEnabledTime then
209
- bestEnabledTime = enableTime
210
- bestMode = inputMode
211
- end
212
- end
213
-
214
- self._activeMode.Value = bestMode
215
- end
216
-
217
- --[=[
218
- Cleans up the input mode selector.
219
-
220
- :::info
221
- This should be called whenever the mode selector is done being used.
222
- :::
223
- ]=]
224
- function InputModeSelector:Destroy()
225
- self._maid:DoCleaning()
226
- setmetatable(self, nil)
227
- end
228
-
229
- return InputModeSelector