dualsense-ts 5.5.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/MIGRATION_GUIDE.md +19 -0
- package/README.md +68 -3
- package/dist/dualsense.d.ts +4 -0
- package/dist/dualsense.d.ts.map +1 -1
- package/dist/dualsense.js +47 -9
- package/dist/dualsense.js.map +1 -1
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/index.d.ts.map +1 -1
- package/dist/elements/index.js +1 -0
- package/dist/elements/index.js.map +1 -1
- package/dist/elements/trigger.d.ts +3 -0
- package/dist/elements/trigger.d.ts.map +1 -1
- package/dist/elements/trigger.js +3 -0
- package/dist/elements/trigger.js.map +1 -1
- package/dist/elements/trigger_feedback.d.ts +109 -0
- package/dist/elements/trigger_feedback.d.ts.map +1 -0
- package/dist/elements/trigger_feedback.js +168 -0
- package/dist/elements/trigger_feedback.js.map +1 -0
- package/dist/hid/bt_checksum.d.ts +2 -0
- package/dist/hid/bt_checksum.d.ts.map +1 -0
- package/dist/hid/bt_checksum.js +60 -0
- package/dist/hid/bt_checksum.js.map +1 -0
- package/dist/hid/command.d.ts +8 -18
- package/dist/hid/command.d.ts.map +1 -1
- package/dist/hid/dualsense_hid.d.ts +6 -5
- package/dist/hid/dualsense_hid.d.ts.map +1 -1
- package/dist/hid/dualsense_hid.js +38 -20
- package/dist/hid/dualsense_hid.js.map +1 -1
- package/dist/hid/hid_provider.d.ts +1 -0
- package/dist/hid/hid_provider.d.ts.map +1 -1
- package/dist/hid/index.d.ts +1 -0
- package/dist/hid/index.d.ts.map +1 -1
- package/dist/hid/index.js +1 -0
- package/dist/hid/index.js.map +1 -1
- package/dist/hid/node_hid_provider.d.ts +1 -0
- package/dist/hid/node_hid_provider.d.ts.map +1 -1
- package/dist/hid/web_hid_provider.d.ts.map +1 -1
- package/dist/hid/web_hid_provider.js +3 -1
- package/dist/hid/web_hid_provider.js.map +1 -1
- package/nodehid_example/debug.ts +122 -39
- package/package.json +5 -5
- package/src/dualsense.ts +55 -12
- package/src/elements/index.ts +1 -0
- package/src/elements/trigger.ts +4 -0
- package/src/elements/trigger_feedback.ts +267 -0
- package/src/hid/bt_checksum.spec.ts +15 -0
- package/src/hid/bt_checksum.ts +58 -0
- package/src/hid/command.ts +24 -34
- package/src/hid/dualsense_hid.ts +54 -23
- package/src/hid/index.ts +1 -0
- package/src/hid/web_hid_provider.ts +3 -1
- package/webhid_example/build/asset-manifest.json +6 -6
- package/webhid_example/build/index.html +1 -1
- package/webhid_example/build/static/css/{main.237f8cfa.css → main.9393bbb9.css} +2 -2
- package/webhid_example/build/static/css/main.9393bbb9.css.map +1 -0
- package/webhid_example/build/static/js/main.d804191f.js +3 -0
- package/webhid_example/build/static/js/main.d804191f.js.map +1 -0
- package/webhid_example/src/App.tsx +59 -18
- package/webhid_example/src/hud/ControllerConnection.tsx +59 -57
- package/webhid_example/src/hud/Debugger.tsx +83 -79
- package/webhid_example/src/hud/Gyro.tsx +48 -53
- package/webhid_example/src/hud/HUDLayout.tsx +2 -10
- package/webhid_example/src/hud/Reticle.tsx +12 -62
- package/webhid_example/src/hud/RightStick.tsx +26 -0
- package/webhid_example/src/hud/StickVisualization.tsx +81 -0
- package/webhid_example/src/hud/TriggerEffectControls.tsx +417 -0
- package/webhid_example/src/hud/index.tsx +3 -0
- package/webhid_example/src/index.css +20 -1
- package/webhid_example/build/static/css/main.237f8cfa.css.map +0 -1
- package/webhid_example/build/static/js/main.0432376e.js +0 -3
- package/webhid_example/build/static/js/main.0432376e.js.map +0 -1
- /package/webhid_example/build/static/js/{main.0432376e.js.LICENSE.txt → main.d804191f.js.LICENSE.txt} +0 -0
package/MIGRATION_GUIDE.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Migration Guide
|
|
2
2
|
|
|
3
|
+
### v5 to v6
|
|
4
|
+
|
|
5
|
+
`TriggerMode` is deprecated. The low-level `DualsenseHID` methods for setting trigger effects now accept 11-byte effect blocks instead of individual mode/value pairs.
|
|
6
|
+
|
|
7
|
+
Use the new element-based API instead:
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { TriggerEffect } from "dualsense-ts";
|
|
11
|
+
|
|
12
|
+
controller.right.trigger.feedback.set({
|
|
13
|
+
effect: TriggerEffect.Weapon,
|
|
14
|
+
start: 0.2,
|
|
15
|
+
end: 0.6,
|
|
16
|
+
strength: 0.9,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
controller.right.trigger.feedback.reset();
|
|
20
|
+
```
|
|
21
|
+
|
|
3
22
|
### v4 to v5
|
|
4
23
|
|
|
5
24
|
`node-hid` is now an optional peer dependency, simplifying the use of this library in the browser.
|
package/README.md
CHANGED
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
This module provides a natural interface for your DualSense controller.
|
|
4
4
|
|
|
5
|
+
**[Try it in your browser](https://nsfm.github.io/dualsense-ts/)** — connect a DualSense controller and explore inputs, rumble, and adaptive trigger effects with the interactive demo.
|
|
6
|
+
|
|
5
7
|
## Getting started
|
|
6
8
|
|
|
7
9
|
### Installation
|
|
8
10
|
|
|
9
|
-
[This package is distributed via npm](https://npmjs.
|
|
11
|
+
[This package is distributed via npm](https://www.npmjs.com/package/dualsense-ts). Install it the usual way:
|
|
10
12
|
|
|
11
13
|
- `npm add dualsense-ts`
|
|
12
14
|
|
|
@@ -37,6 +39,8 @@ controller.connection.on("change", ({ active }) = > {
|
|
|
37
39
|
});
|
|
38
40
|
```
|
|
39
41
|
|
|
42
|
+
This package supports both wired and Bluetooth devices. While connected via Bluetooth, `controller.wireless` will return `true`.
|
|
43
|
+
|
|
40
44
|
### Input APIs
|
|
41
45
|
|
|
42
46
|
`dualsense-ts` provides several interfaces for reading input:
|
|
@@ -60,7 +64,7 @@ controller.left.analog.magnitude; // 0.23, 0 to 1
|
|
|
60
64
|
|
|
61
65
|
// Touchpad - each touch point works like an analog input
|
|
62
66
|
controller.touchpad.right.contact.state; // false
|
|
63
|
-
|
|
67
|
+
controller.touchpad.right.x; // -0.44, -1 to 1
|
|
64
68
|
```
|
|
65
69
|
|
|
66
70
|
- _Callbacks_: Each input is an EventEmitter or EventTarget that provides `input`, `press`, `release`, and `change` events
|
|
@@ -130,7 +134,7 @@ controller.accelerometer.z.on("change", ({ force }) => {
|
|
|
130
134
|
|
|
131
135
|
#### Rumble
|
|
132
136
|
|
|
133
|
-
|
|
137
|
+
The controller has two independent rumble motors. The left motor is larger and produces a stronger, lower-frequency rumble, while the right motor is smaller and produces a lighter, higher-frequency vibration. They are controlled independently:
|
|
134
138
|
|
|
135
139
|
```typescript
|
|
136
140
|
controller.rumble(1.0); // 100% rumble intensity
|
|
@@ -148,6 +152,67 @@ controller.right.trigger.on("change", (trigger) => {
|
|
|
148
152
|
});
|
|
149
153
|
```
|
|
150
154
|
|
|
155
|
+
#### Adaptive Triggers
|
|
156
|
+
|
|
157
|
+
Haptic trigger feedback is controlled via `controller.left.trigger.feedback` / `controller.right.trigger.feedback`. All position and strength values are normalized 0–1.
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import { Dualsense, TriggerEffect } from "dualsense-ts";
|
|
161
|
+
|
|
162
|
+
const controller = new Dualsense();
|
|
163
|
+
|
|
164
|
+
// Continuous resistance starting at 30% travel
|
|
165
|
+
controller.right.trigger.feedback.set({
|
|
166
|
+
effect: TriggerEffect.Feedback,
|
|
167
|
+
position: 0.3,
|
|
168
|
+
strength: 0.8,
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Weapon trigger — resistance with snap release
|
|
172
|
+
controller.right.trigger.feedback.set({
|
|
173
|
+
effect: TriggerEffect.Weapon,
|
|
174
|
+
start: 0.2,
|
|
175
|
+
end: 0.6,
|
|
176
|
+
strength: 0.9,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
// Vibration with frequency
|
|
180
|
+
controller.right.trigger.feedback.set({
|
|
181
|
+
effect: TriggerEffect.Vibration,
|
|
182
|
+
position: 0.1,
|
|
183
|
+
amplitude: 0.7,
|
|
184
|
+
frequency: 40, // in Hz, 0 - 255
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Reset to default linear feel
|
|
188
|
+
controller.right.trigger.feedback.reset();
|
|
189
|
+
|
|
190
|
+
// Reset both triggers
|
|
191
|
+
controller.resetTriggerFeedback();
|
|
192
|
+
|
|
193
|
+
// Read current config
|
|
194
|
+
console.log(controller.right.trigger.feedback.config);
|
|
195
|
+
console.log(controller.right.trigger.feedback.effect); // TriggerEffect.Off
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Feedback state is automatically restored if the controller disconnects and reconnects — no handling required on your end.
|
|
199
|
+
|
|
200
|
+
#### Trigger effects
|
|
201
|
+
|
|
202
|
+
| Effect | Description |
|
|
203
|
+
| ------------------------- | ---------------------------------------------------------- |
|
|
204
|
+
| `TriggerEffect.Off` | No resistance (default linear feel) |
|
|
205
|
+
| `TriggerEffect.Feedback` | Zone-based continuous resistance from a start position |
|
|
206
|
+
| `TriggerEffect.Weapon` | Resistance with a snap release point |
|
|
207
|
+
| `TriggerEffect.Bow` | Weapon feel with snap-back force |
|
|
208
|
+
| `TriggerEffect.Galloping` | Rhythmic two-stroke oscillation |
|
|
209
|
+
| `TriggerEffect.Vibration` | Zone-based oscillation with amplitude and frequency |
|
|
210
|
+
| `TriggerEffect.Machine` | Dual-amplitude vibration with frequency and period control |
|
|
211
|
+
|
|
212
|
+
Each effect accepts a unique set of configuration options — your editor's type hints will guide you through the available parameters for each effect. The [interactive demo](https://nsfm.github.io/dualsense-ts/) includes full slider controls for every effect and parameter, making it a great tool for finding the right values.
|
|
213
|
+
|
|
214
|
+
Effect names are based on [Nielk1's DualSense trigger effect documentation](https://gist.github.com/Nielk1/6d54cc2c00d2201ccb8c2720ad7538db).
|
|
215
|
+
|
|
151
216
|
### With React
|
|
152
217
|
|
|
153
218
|
Check out [the example app](./webhid_example/) for more details.
|
package/dist/dualsense.d.ts
CHANGED
|
@@ -71,8 +71,12 @@ export declare class Dualsense extends Input<Dualsense> {
|
|
|
71
71
|
/** A virtual button representing whether or not a controller is connected */
|
|
72
72
|
readonly connection: Momentary;
|
|
73
73
|
get active(): boolean;
|
|
74
|
+
/** Returns `true` if the controller is connected via Bluetooth */
|
|
75
|
+
get wireless(): boolean;
|
|
74
76
|
constructor(params?: DualsenseParams);
|
|
75
77
|
private get rumbleIntensity();
|
|
78
|
+
/** Reset adaptive trigger feedback on both sides to the default linear feel */
|
|
79
|
+
resetTriggerFeedback(): void;
|
|
76
80
|
/** Check or adjust rumble intensity evenly across both sides of the controller */
|
|
77
81
|
rumble(intensity?: Intensity): number;
|
|
78
82
|
/** Distributes HID event values to the controller's inputs */
|
package/dist/dualsense.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dualsense.d.ts","sourceRoot":"","sources":["../src/dualsense.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,IAAI,EACJ,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,QAAQ,EACR,SAAS,EACT,eAAe,EACf,aAAa,EACb,mBAAmB,EACpB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,EAAY,WAAW,EAAE,MAAM,SAAS,CAAC;AACvD,OAAO,EAEL,YAAY,EAGb,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,oEAAoE;AACpE,MAAM,WAAW,eAAgB,SAAQ,WAAW;IAClD,oEAAoE;IACpE,GAAG,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1B,0CAA0C;IAC1C,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,mCAAmC;IACnC,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,sCAAsC;IACtC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,qCAAqC;IACrC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,qCAAqC;IACrC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,oCAAoC;IACpC,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,qCAAqC;IACrC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,oCAAoC;IACpC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,uCAAuC;IACvC,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,iCAAiC;IACjC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,qCAAqC;IACrC,aAAa,CAAC,EAAE,mBAAmB,CAAC;CACrC;AAED,wCAAwC;AACxC,qBAAa,SAAU,SAAQ,KAAK,CAAC,SAAS,CAAC;IAC7C,SAAgB,KAAK,EAAE,SAAS,CAAQ;IAExC,6BAA6B;IAC7B,SAAgB,EAAE,EAAE,SAAS,CAAC;IAC9B,uCAAuC;IACvC,SAAgB,IAAI,EAAE,IAAI,CAAC;IAC3B,yBAAyB;IACzB,SAAgB,OAAO,EAAE,SAAS,CAAC;IACnC,wBAAwB;IACxB,SAAgB,MAAM,EAAE,SAAS,CAAC;IAClC,0BAA0B;IAC1B,SAAgB,QAAQ,EAAE,SAAS,CAAC;IACpC,wBAAwB;IACxB,SAAgB,MAAM,EAAE,SAAS,CAAC;IAClC,6BAA6B;IAC7B,SAAgB,KAAK,EAAE,SAAS,CAAC;IACjC,wBAAwB;IACxB,SAAgB,MAAM,EAAE,SAAS,CAAC;IAClC,0CAA0C;IAC1C,SAAgB,IAAI,EAAE,IAAI,CAAC;IAC3B,gDAAgD;IAChD,SAAgB,IAAI,EAAE,QAAQ,CAAC;IAC/B,iDAAiD;IACjD,SAAgB,KAAK,EAAE,QAAQ,CAAC;IAChC,uDAAuD;IACvD,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IACnC,+CAA+C;IAC/C,SAAgB,SAAS,EAAE,SAAS,CAAC;IACrC,kDAAkD;IAClD,SAAgB,aAAa,EAAE,aAAa,CAAC;IAE7C,kEAAkE;IAClE,SAAgB,GAAG,EAAE,YAAY,CAAC;IAElC,6EAA6E;IAC7E,SAAgB,UAAU,EAAE,SAAS,CAAC;IAEtC,IAAW,MAAM,IAAI,OAAO,CAI3B;gBAEW,MAAM,GAAE,eAAoB;
|
|
1
|
+
{"version":3,"file":"dualsense.d.ts","sourceRoot":"","sources":["../src/dualsense.ts"],"names":[],"mappings":"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"}
|
package/dist/dualsense.js
CHANGED
|
@@ -9,6 +9,10 @@ class Dualsense extends input_1.Input {
|
|
|
9
9
|
get active() {
|
|
10
10
|
return Object.values(this).some((input) => input !== this && input instanceof input_1.Input && input.active);
|
|
11
11
|
}
|
|
12
|
+
/** Returns `true` if the controller is connected via Bluetooth */
|
|
13
|
+
get wireless() {
|
|
14
|
+
return this.hid.wireless;
|
|
15
|
+
}
|
|
12
16
|
constructor(params = {}) {
|
|
13
17
|
super(params);
|
|
14
18
|
this.state = this;
|
|
@@ -94,29 +98,63 @@ class Dualsense extends input_1.Input {
|
|
|
94
98
|
this.hid.register((state) => {
|
|
95
99
|
this.processHID(state);
|
|
96
100
|
});
|
|
101
|
+
const rumbleMemo = { left: -1, right: -1 };
|
|
102
|
+
const triggerFeedbackMemo = { left: "", right: "" };
|
|
97
103
|
/** Refresh connection state */
|
|
104
|
+
let lastConnected = false;
|
|
98
105
|
setInterval(() => {
|
|
99
106
|
const { provider: { connected }, } = this.hid;
|
|
100
107
|
this.connection[input_1.InputSet](connected);
|
|
108
|
+
if (connected && !lastConnected) {
|
|
109
|
+
// Invalidate memo so the output loop restores desired state on reconnect.
|
|
110
|
+
triggerFeedbackMemo.left = "";
|
|
111
|
+
triggerFeedbackMemo.right = "";
|
|
112
|
+
}
|
|
113
|
+
lastConnected = connected;
|
|
101
114
|
if (!connected)
|
|
102
115
|
this.hid.provider.connect();
|
|
103
116
|
}, 200);
|
|
104
|
-
/** Refresh
|
|
105
|
-
const rumbleMemo = { left: -1, right: -1 };
|
|
117
|
+
/** Refresh output state (rumble + trigger feedback) */
|
|
106
118
|
setInterval(() => {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
rumbleMemo.
|
|
119
|
+
if (!this.connection.active)
|
|
120
|
+
return;
|
|
121
|
+
const leftRumble = this.left.rumble();
|
|
122
|
+
const rightRumble = this.right.rumble();
|
|
123
|
+
if (leftRumble !== rumbleMemo.left || rightRumble !== rumbleMemo.right) {
|
|
124
|
+
this.hid.setRumble(leftRumble * 255, rightRumble * 255);
|
|
125
|
+
rumbleMemo.left = leftRumble;
|
|
126
|
+
rumbleMemo.right = rightRumble;
|
|
127
|
+
}
|
|
128
|
+
const leftFeedback = this.left.trigger.feedback;
|
|
129
|
+
const rightFeedback = this.right.trigger.feedback;
|
|
130
|
+
const leftKey = leftFeedback.toKey();
|
|
131
|
+
const rightKey = rightFeedback.toKey();
|
|
132
|
+
const feedbackChanged = leftKey !== triggerFeedbackMemo.left ||
|
|
133
|
+
rightKey !== triggerFeedbackMemo.right;
|
|
134
|
+
if (feedbackChanged) {
|
|
135
|
+
// Force rumble into the same batch so MotorPower scope bit is always present.
|
|
136
|
+
this.hid.setRumble(leftRumble * 255, rightRumble * 255);
|
|
137
|
+
rumbleMemo.left = leftRumble;
|
|
138
|
+
rumbleMemo.right = rightRumble;
|
|
139
|
+
}
|
|
140
|
+
if (leftKey !== triggerFeedbackMemo.left) {
|
|
141
|
+
this.hid.setLeftTriggerFeedback(leftFeedback.toBytes());
|
|
142
|
+
triggerFeedbackMemo.left = leftKey;
|
|
143
|
+
}
|
|
144
|
+
if (rightKey !== triggerFeedbackMemo.right) {
|
|
145
|
+
this.hid.setRightTriggerFeedback(rightFeedback.toBytes());
|
|
146
|
+
triggerFeedbackMemo.right = rightKey;
|
|
114
147
|
}
|
|
115
148
|
}, 1000 / 30);
|
|
116
149
|
}
|
|
117
150
|
get rumbleIntensity() {
|
|
118
151
|
return (this.left.rumble() + this.right.rumble()) / 2;
|
|
119
152
|
}
|
|
153
|
+
/** Reset adaptive trigger feedback on both sides to the default linear feel */
|
|
154
|
+
resetTriggerFeedback() {
|
|
155
|
+
this.left.trigger.feedback.reset();
|
|
156
|
+
this.right.trigger.feedback.reset();
|
|
157
|
+
}
|
|
120
158
|
/** Check or adjust rumble intensity evenly across both sides of the controller */
|
|
121
159
|
rumble(intensity) {
|
|
122
160
|
this.left.rumble(intensity);
|
package/dist/dualsense.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dualsense.js","sourceRoot":"","sources":["../src/dualsense.ts"],"names":[],"mappings":";;;AAAA,yCAYoB;AACpB,mCAAuD;AACvD,+BAKe;AAqCf,wCAAwC;AACxC,MAAa,SAAU,SAAQ,aAAgB;IAsC7C,IAAW,MAAM;QACf,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAC7B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,YAAY,aAAK,IAAI,KAAK,CAAC,MAAM,CACpE,CAAC;IACJ,CAAC;IAED,YAAY,SAA0B,EAAE;QACtC,KAAK,CAAC,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"dualsense.js","sourceRoot":"","sources":["../src/dualsense.ts"],"names":[],"mappings":";;;AAAA,yCAYoB;AACpB,mCAAuD;AACvD,+BAKe;AAqCf,wCAAwC;AACxC,MAAa,SAAU,SAAQ,aAAgB;IAsC7C,IAAW,MAAM;QACf,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAC7B,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,YAAY,aAAK,IAAI,KAAK,CAAC,MAAM,CACpE,CAAC;IACJ,CAAC;IAED,kEAAkE;IAClE,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC3B,CAAC;IAED,YAAY,SAA0B,EAAE;QACtC,KAAK,CAAC,MAAM,CAAC,CAAC;QAjDA,UAAK,GAAc,IAAI,CAAC;QAmDtC,IAAI,CAAC,EAAE,GAAG,IAAI,oBAAS,CAAC;YACtB,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,MAAM;YACZ,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC;SACrB,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,IAAI,eAAI,CAAC;YACnB,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,MAAM;YACZ,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;SACvB,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,GAAG,IAAI,oBAAS,CAAC;YAC3B,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,SAAS;YACf,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;SAC1B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,oBAAS,CAAC;YAC1B,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,QAAQ;YACd,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,GAAG,IAAI,oBAAS,CAAC;YAC5B,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,UAAU;YAChB,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,oBAAS,CAAC;YAC1B,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,QAAQ;YACd,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,IAAI,oBAAS,CAAC;YACzB,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,OAAO;YACb,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SACxB,CAAC,CAAC;QACH,IAAI,CAAC,MAAM,GAAG,IAAI,oBAAS,CAAC;YAC1B,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,QAAQ;YACd,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,IAAI,eAAI,CAAC;YACnB,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,OAAO;YACb,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;SACvB,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,IAAI,mBAAQ,CAAC;YACvB,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,MAAM;YACZ,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;SACvB,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,IAAI,mBAAQ,CAAC;YACxB,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,OAAO;YACb,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;SACxB,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,GAAG,IAAI,mBAAQ,CAAC;YAC3B,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,UAAU;YAChB,GAAG,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;SAC3B,CAAC,CAAC;QACH,IAAI,CAAC,UAAU,GAAG,IAAI,oBAAS,CAAC;YAC9B,IAAI,EAAE,IAAI;YACV,IAAI,EAAE,WAAW;YACjB,GAAG,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC;SACzB,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,GAAG,IAAI,oBAAS,CAAC;YAC7B,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,IAAI;YACf,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;SAC5B,CAAC,CAAC;QACH,IAAI,CAAC,aAAa,GAAG,IAAI,wBAAa,CAAC;YACrC,IAAI,EAAE,GAAG;YACT,IAAI,EAAE,eAAe;YACrB,SAAS,EAAE,IAAI;YACf,GAAG,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC;SAChC,CAAC,CAAC;QAEH,IAAI,CAAC,UAAU,CAAC,gBAAQ,CAAC,CAAC,KAAK,CAAC,CAAC;QACjC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,IAAI,kBAAY,CAAC,IAAI,yBAAmB,EAAE,CAAC,CAAC;QACrE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,KAAwB,EAAE,EAAE;YAC7C,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;QAC3C,MAAM,mBAAmB,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAEpD,+BAA+B;QAC/B,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,WAAW,CAAC,GAAG,EAAE;YACf,MAAM,EACJ,QAAQ,EAAE,EAAE,SAAS,EAAE,GACxB,GAAG,IAAI,CAAC,GAAG,CAAC;YAEb,IAAI,CAAC,UAAU,CAAC,gBAAQ,CAAC,CAAC,SAAS,CAAC,CAAC;YACrC,IAAI,SAAS,IAAI,CAAC,aAAa,EAAE;gBAC/B,0EAA0E;gBAC1E,mBAAmB,CAAC,IAAI,GAAG,EAAE,CAAC;gBAC9B,mBAAmB,CAAC,KAAK,GAAG,EAAE,CAAC;aAChC;YACD,aAAa,GAAG,SAAS,CAAC;YAC1B,IAAI,CAAC,SAAS;gBAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC9C,CAAC,EAAE,GAAG,CAAC,CAAC;QAER,uDAAuD;QACvD,WAAW,CAAC,GAAG,EAAE;YACf,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM;gBAAE,OAAO;YAEpC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACtC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACxC,IAAI,UAAU,KAAK,UAAU,CAAC,IAAI,IAAI,WAAW,KAAK,UAAU,CAAC,KAAK,EAAE;gBACtE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,GAAG,GAAG,EAAE,WAAW,GAAG,GAAG,CAAC,CAAC;gBACxD,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC;gBAC7B,UAAU,CAAC,KAAK,GAAG,WAAW,CAAC;aAChC;YAED,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;YAChD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YAClD,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC;YACrC,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC;YACvC,MAAM,eAAe,GACnB,OAAO,KAAK,mBAAmB,CAAC,IAAI;gBACpC,QAAQ,KAAK,mBAAmB,CAAC,KAAK,CAAC;YAEzC,IAAI,eAAe,EAAE;gBACnB,8EAA8E;gBAC9E,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,GAAG,GAAG,EAAE,WAAW,GAAG,GAAG,CAAC,CAAC;gBACxD,UAAU,CAAC,IAAI,GAAG,UAAU,CAAC;gBAC7B,UAAU,CAAC,KAAK,GAAG,WAAW,CAAC;aAChC;YAED,IAAI,OAAO,KAAK,mBAAmB,CAAC,IAAI,EAAE;gBACxC,IAAI,CAAC,GAAG,CAAC,sBAAsB,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,CAAC;gBACxD,mBAAmB,CAAC,IAAI,GAAG,OAAO,CAAC;aACpC;YACD,IAAI,QAAQ,KAAK,mBAAmB,CAAC,KAAK,EAAE;gBAC1C,IAAI,CAAC,GAAG,CAAC,uBAAuB,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,CAAC;gBAC1D,mBAAmB,CAAC,KAAK,GAAG,QAAQ,CAAC;aACtC;QACH,CAAC,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IAChB,CAAC;IAED,IAAY,eAAe;QACzB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;IAED,+EAA+E;IACxE,oBAAoB;QACzB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACtC,CAAC;IAED,kFAAkF;IAC3E,MAAM,CAAC,SAAqB;QACjC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED,8DAA8D;IACtD,UAAU,CAAC,KAAwB;QACzC,IAAI,CAAC,EAAE,CAAC,gBAAQ,CAAC,CAAC,KAAK,yCAAqB,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,CAAC,gBAAQ,CAAC,CAAC,KAAK,iCAAiB,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,+BAAgB,CAAC,CAAC;QAE7C,IAAI,CAAC,IAAI,CAAC,gBAAQ,CAAC,CAAC,KAAK,2BAAc,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,+BAAgB,CAAC,CAAC;QAElD,IAAI,CAAC,QAAQ,CAAC,gBAAQ,CAAC,CAAC,KAAK,mCAAkB,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,+BAAgB,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,CAAC,gBAAQ,CAAC,CAAC,KAAK,6BAAe,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,+BAAgB,CAAC,CAAC;QAE7C,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,gBAAQ,CAAC,CAAC,KAAK,uBAAY,CAAC,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAQ,CAAC,CAAC,KAAK,2BAAc,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAQ,CAAC,CAAC,KAAK,6BAAe,CAAC,CAAC;QAChD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAQ,CAAC,CAAC,KAAK,2BAAc,CAAC,CAAC;QAE9C,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,yCAAqB,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,iCAAiB,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,iCAAiB,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAQ,CAAC,CAAC,KAAK,6CAAuB,CAAC,CAAC;QACnE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAQ,CAAC,CAAC,KAAK,mCAAkB,CAAC,CAAC;QAC9D,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,iCAAiB,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,iCAAiB,CAAC,CAAC;QACxD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAQ,CAAC,CAAC,KAAK,6CAAuB,CAAC,CAAC;QACpE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAQ,CAAC,CAAC,KAAK,mCAAkB,CAAC,CAAC;QAE/D,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,gCAAqB,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,gCAAqB,CAAC,CAAC;QACzD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,qCAA0B,CAAC,CAAC;QACnE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,+BAAoB,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,gBAAQ,CAAC,CAAC,KAAK,gCAAqB,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,4CAA2B,CAAC,CAAC;QAErE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,iCAAsB,CAAC,CAAC;QAC3D,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,iCAAsB,CAAC,CAAC;QAC3D,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,sCAA2B,CAAC,CAAC;QACrE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,gCAAqB,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,gBAAQ,CAAC,CAAC,KAAK,iCAAsB,CAAC,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,gBAAQ,CAAC,CAAC,KAAK,6CAA4B,CAAC,CAAC;QAEvE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,6BAAe,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,6BAAe,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,6BAAe,CAAC,CAAC;QACjD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,+BAAgB,CAAC,CAAC;QACtD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,+BAAgB,CAAC,CAAC;QACtD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,gBAAQ,CAAC,CAAC,KAAK,+BAAgB,CAAC,CAAC;IACxD,CAAC;CACF;AArQD,8BAqQC"}
|
package/dist/elements/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/elements/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/elements/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,WAAW,CAAC;AAC1B,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC"}
|
package/dist/elements/index.js
CHANGED
|
@@ -29,5 +29,6 @@ __exportStar(require("./mute"), exports);
|
|
|
29
29
|
__exportStar(require("./touch"), exports);
|
|
30
30
|
__exportStar(require("./touchpad"), exports);
|
|
31
31
|
__exportStar(require("./trigger"), exports);
|
|
32
|
+
__exportStar(require("./trigger_feedback"), exports);
|
|
32
33
|
__exportStar(require("./unisense"), exports);
|
|
33
34
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/elements/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,kDAAgC;AAChC,2CAAyB;AACzB,yCAAuB;AACvB,yCAAuB;AACvB,8CAA4B;AAC5B,8CAA4B;AAC5B,8CAA4B;AAC5B,2CAAyB;AACzB,yCAAuB;AACvB,0CAAwB;AACxB,6CAA2B;AAC3B,4CAA0B;AAC1B,6CAA2B"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/elements/index.ts"],"names":[],"mappings":";AAAA;;GAEG;;;;;;;;;;;;;;;;AAEH,kDAAgC;AAChC,2CAAyB;AACzB,yCAAuB;AACvB,yCAAuB;AACvB,8CAA4B;AAC5B,8CAA4B;AAC5B,8CAA4B;AAC5B,2CAAyB;AACzB,yCAAuB;AACvB,0CAAwB;AACxB,6CAA2B;AAC3B,4CAA0B;AAC1B,qDAAmC;AACnC,6CAA2B"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { Input } from "../input";
|
|
2
2
|
import { Magnitude } from "../math";
|
|
3
3
|
import { Momentary } from "./momentary";
|
|
4
|
+
import { TriggerFeedback } from "./trigger_feedback";
|
|
4
5
|
export declare class Trigger extends Input<Magnitude> {
|
|
5
6
|
state: Magnitude;
|
|
6
7
|
button: Momentary;
|
|
8
|
+
/** Desired adaptive trigger feedback state */
|
|
9
|
+
readonly feedback: TriggerFeedback;
|
|
7
10
|
get active(): boolean;
|
|
8
11
|
get pressure(): Magnitude;
|
|
9
12
|
get magnitude(): Magnitude;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../../src/elements/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"trigger.d.ts","sourceRoot":"","sources":["../../src/elements/trigger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,qBAAa,OAAQ,SAAQ,KAAK,CAAC,SAAS,CAAC;IACpC,KAAK,EAAE,SAAS,CAAK;IAErB,MAAM,EAAE,SAAS,CAAmB;IAE3C,8CAA8C;IAC9C,SAAgB,QAAQ,kBAAyB;IAEjD,IAAW,MAAM,IAAI,OAAO,CAE3B;IAED,IAAW,QAAQ,IAAI,SAAS,CAE/B;IAED,IAAW,SAAS,IAAI,SAAS,CAEhC;IAEM,OAAO,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;CAG1C"}
|
package/dist/elements/trigger.js
CHANGED
|
@@ -3,11 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Trigger = void 0;
|
|
4
4
|
const input_1 = require("../input");
|
|
5
5
|
const momentary_1 = require("./momentary");
|
|
6
|
+
const trigger_feedback_1 = require("./trigger_feedback");
|
|
6
7
|
class Trigger extends input_1.Input {
|
|
7
8
|
constructor() {
|
|
8
9
|
super(...arguments);
|
|
9
10
|
this.state = 0;
|
|
10
11
|
this.button = new momentary_1.Momentary();
|
|
12
|
+
/** Desired adaptive trigger feedback state */
|
|
13
|
+
this.feedback = new trigger_feedback_1.TriggerFeedback();
|
|
11
14
|
}
|
|
12
15
|
get active() {
|
|
13
16
|
return this.state > 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trigger.js","sourceRoot":"","sources":["../../src/elements/trigger.ts"],"names":[],"mappings":";;;AAAA,oCAAiC;AAEjC,2CAAwC;
|
|
1
|
+
{"version":3,"file":"trigger.js","sourceRoot":"","sources":["../../src/elements/trigger.ts"],"names":[],"mappings":";;;AAAA,oCAAiC;AAEjC,2CAAwC;AACxC,yDAAqD;AAErD,MAAa,OAAQ,SAAQ,aAAgB;IAA7C;;QACS,UAAK,GAAc,CAAC,CAAC;QAErB,WAAM,GAAc,IAAI,qBAAS,EAAE,CAAC;QAE3C,8CAA8C;QAC9B,aAAQ,GAAG,IAAI,kCAAe,EAAE,CAAC;IAiBnD,CAAC;IAfC,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,IAAW,QAAQ;QACjB,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAEM,OAAO,CAAC,KAAgB;QAC7B,OAAO,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC;IAC9B,CAAC;CACF;AAvBD,0BAuBC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/** Canonical trigger effect types from the DualSense firmware */
|
|
2
|
+
export declare enum TriggerEffect {
|
|
3
|
+
/** No resistance — default linear feel */
|
|
4
|
+
Off = "off",
|
|
5
|
+
/** Zone-based continuous resistance */
|
|
6
|
+
Feedback = "feedback",
|
|
7
|
+
/** Resistance with a snap release point, like a weapon trigger */
|
|
8
|
+
Weapon = "weapon",
|
|
9
|
+
/** Weapon feel with snap-back force, like drawing a bow */
|
|
10
|
+
Bow = "bow",
|
|
11
|
+
/** Rhythmic two-stroke oscillation */
|
|
12
|
+
Galloping = "galloping",
|
|
13
|
+
/** Zone-based oscillation with configurable amplitude and frequency */
|
|
14
|
+
Vibration = "vibration",
|
|
15
|
+
/** Dual-amplitude vibration with frequency and period control */
|
|
16
|
+
Machine = "machine"
|
|
17
|
+
}
|
|
18
|
+
/** Zone-based resistance with per-zone force control */
|
|
19
|
+
export interface FeedbackEffect {
|
|
20
|
+
effect: TriggerEffect.Feedback;
|
|
21
|
+
/** Where resistance begins along trigger travel (0-1) */
|
|
22
|
+
position: number;
|
|
23
|
+
/** Resistance strength (0-1, maps to firmware's 1-8 scale) */
|
|
24
|
+
strength: number;
|
|
25
|
+
}
|
|
26
|
+
/** Resistance with a start position, snap release point, and force */
|
|
27
|
+
export interface WeaponEffect {
|
|
28
|
+
effect: TriggerEffect.Weapon;
|
|
29
|
+
/** Where resistance begins (0-1, maps to zones 2-7) */
|
|
30
|
+
start: number;
|
|
31
|
+
/** Where snap release occurs (0-1, maps to zones 3-8, must be after start) */
|
|
32
|
+
end: number;
|
|
33
|
+
/** Resistance strength (0-1) */
|
|
34
|
+
strength: number;
|
|
35
|
+
}
|
|
36
|
+
/** Weapon feel with snap-back force */
|
|
37
|
+
export interface BowEffect {
|
|
38
|
+
effect: TriggerEffect.Bow;
|
|
39
|
+
/** Where resistance begins (0-1) */
|
|
40
|
+
start: number;
|
|
41
|
+
/** Where snap-back occurs (0-1, must be after start) */
|
|
42
|
+
end: number;
|
|
43
|
+
/** Pull strength (0-1) */
|
|
44
|
+
strength: number;
|
|
45
|
+
/** Snap-back force (0-1) */
|
|
46
|
+
snapForce: number;
|
|
47
|
+
}
|
|
48
|
+
/** Rhythmic two-stroke oscillation */
|
|
49
|
+
export interface GallopingEffect {
|
|
50
|
+
effect: TriggerEffect.Galloping;
|
|
51
|
+
/** Where effect begins (0-1) */
|
|
52
|
+
start: number;
|
|
53
|
+
/** Where effect ends (0-1) */
|
|
54
|
+
end: number;
|
|
55
|
+
/** First foot timing (0-1, maps to 0-6) */
|
|
56
|
+
firstFoot: number;
|
|
57
|
+
/** Second foot timing (0-1, maps to 0-7, must be after firstFoot) */
|
|
58
|
+
secondFoot: number;
|
|
59
|
+
/** Oscillation frequency in Hz (1-255) */
|
|
60
|
+
frequency: number;
|
|
61
|
+
}
|
|
62
|
+
/** Zone-based oscillation with amplitude and frequency control */
|
|
63
|
+
export interface VibrationEffect {
|
|
64
|
+
effect: TriggerEffect.Vibration;
|
|
65
|
+
/** Where vibration begins along trigger travel (0-1) */
|
|
66
|
+
position: number;
|
|
67
|
+
/** Vibration amplitude (0-1, maps to firmware's 1-8 scale) */
|
|
68
|
+
amplitude: number;
|
|
69
|
+
/** Vibration frequency in Hz (1-255) */
|
|
70
|
+
frequency: number;
|
|
71
|
+
}
|
|
72
|
+
/** Dual-amplitude vibration with frequency and period */
|
|
73
|
+
export interface MachineEffect {
|
|
74
|
+
effect: TriggerEffect.Machine;
|
|
75
|
+
/** Where effect begins (0-1) */
|
|
76
|
+
start: number;
|
|
77
|
+
/** Where effect ends (0-1) */
|
|
78
|
+
end: number;
|
|
79
|
+
/** First amplitude (0-1, maps to 0-7) */
|
|
80
|
+
amplitudeA: number;
|
|
81
|
+
/** Second amplitude (0-1, maps to 0-7) */
|
|
82
|
+
amplitudeB: number;
|
|
83
|
+
/** Vibration frequency in Hz (1-255) */
|
|
84
|
+
frequency: number;
|
|
85
|
+
/** Period in tenths of a second */
|
|
86
|
+
period: number;
|
|
87
|
+
}
|
|
88
|
+
export type TriggerFeedbackConfig = {
|
|
89
|
+
effect: TriggerEffect.Off;
|
|
90
|
+
} | FeedbackEffect | WeaponEffect | BowEffect | GallopingEffect | VibrationEffect | MachineEffect;
|
|
91
|
+
/** Build the 11-byte trigger effect block from a config */
|
|
92
|
+
export declare function buildTriggerEffectBlock(config: TriggerFeedbackConfig): Uint8Array;
|
|
93
|
+
/** Holds the desired adaptive trigger feedback state and translates it for HID output */
|
|
94
|
+
export declare class TriggerFeedback {
|
|
95
|
+
private _config;
|
|
96
|
+
/** The current feedback configuration */
|
|
97
|
+
get config(): TriggerFeedbackConfig;
|
|
98
|
+
/** The current effect type */
|
|
99
|
+
get effect(): TriggerEffect;
|
|
100
|
+
/** Set adaptive trigger feedback */
|
|
101
|
+
set(config: TriggerFeedbackConfig): void;
|
|
102
|
+
/** Reset to no resistance */
|
|
103
|
+
reset(): void;
|
|
104
|
+
/** Build the raw 11-byte effect block for HID output */
|
|
105
|
+
toBytes(): Uint8Array;
|
|
106
|
+
/** String key for change detection in the polling loop */
|
|
107
|
+
toKey(): string;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=trigger_feedback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trigger_feedback.d.ts","sourceRoot":"","sources":["../../src/elements/trigger_feedback.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TriggerFeedback = exports.buildTriggerEffectBlock = exports.TriggerEffect = void 0;
|
|
4
|
+
/** Canonical trigger effect types from the DualSense firmware */
|
|
5
|
+
var TriggerEffect;
|
|
6
|
+
(function (TriggerEffect) {
|
|
7
|
+
/** No resistance — default linear feel */
|
|
8
|
+
TriggerEffect["Off"] = "off";
|
|
9
|
+
/** Zone-based continuous resistance */
|
|
10
|
+
TriggerEffect["Feedback"] = "feedback";
|
|
11
|
+
/** Resistance with a snap release point, like a weapon trigger */
|
|
12
|
+
TriggerEffect["Weapon"] = "weapon";
|
|
13
|
+
/** Weapon feel with snap-back force, like drawing a bow */
|
|
14
|
+
TriggerEffect["Bow"] = "bow";
|
|
15
|
+
/** Rhythmic two-stroke oscillation */
|
|
16
|
+
TriggerEffect["Galloping"] = "galloping";
|
|
17
|
+
/** Zone-based oscillation with configurable amplitude and frequency */
|
|
18
|
+
TriggerEffect["Vibration"] = "vibration";
|
|
19
|
+
/** Dual-amplitude vibration with frequency and period control */
|
|
20
|
+
TriggerEffect["Machine"] = "machine";
|
|
21
|
+
})(TriggerEffect = exports.TriggerEffect || (exports.TriggerEffect = {}));
|
|
22
|
+
// --- Internal translation to raw 11-byte trigger effect block ---
|
|
23
|
+
/** Mode byte values per effect type */
|
|
24
|
+
const EFFECT_MODE = {
|
|
25
|
+
[TriggerEffect.Off]: 0x05,
|
|
26
|
+
[TriggerEffect.Feedback]: 0x21,
|
|
27
|
+
[TriggerEffect.Weapon]: 0x25,
|
|
28
|
+
[TriggerEffect.Bow]: 0x22,
|
|
29
|
+
[TriggerEffect.Galloping]: 0x23,
|
|
30
|
+
[TriggerEffect.Vibration]: 0x26,
|
|
31
|
+
[TriggerEffect.Machine]: 0x27,
|
|
32
|
+
};
|
|
33
|
+
/** Clamp and round a 0-1 value to an integer range */
|
|
34
|
+
function scale(value, max, min = 0) {
|
|
35
|
+
return Math.round(Math.min(max, Math.max(min, value * max)));
|
|
36
|
+
}
|
|
37
|
+
/** Build the 11-byte trigger effect block from a config */
|
|
38
|
+
function buildTriggerEffectBlock(config) {
|
|
39
|
+
const block = new Uint8Array(11).fill(0);
|
|
40
|
+
if (config.effect === TriggerEffect.Off) {
|
|
41
|
+
block[0] = EFFECT_MODE[TriggerEffect.Off];
|
|
42
|
+
return block;
|
|
43
|
+
}
|
|
44
|
+
block[0] = EFFECT_MODE[config.effect];
|
|
45
|
+
switch (config.effect) {
|
|
46
|
+
case TriggerEffect.Feedback: {
|
|
47
|
+
const position = scale(config.position, 9);
|
|
48
|
+
const strength = scale(config.strength, 8, 1);
|
|
49
|
+
const forceValue = (strength - 1) & 0x07;
|
|
50
|
+
let forceZones = 0;
|
|
51
|
+
let activeZones = 0;
|
|
52
|
+
for (let i = position; i < 10; i++) {
|
|
53
|
+
forceZones |= forceValue << (3 * i);
|
|
54
|
+
activeZones |= 1 << i;
|
|
55
|
+
}
|
|
56
|
+
block[1] = activeZones & 0xff;
|
|
57
|
+
block[2] = (activeZones >> 8) & 0xff;
|
|
58
|
+
block[3] = forceZones & 0xff;
|
|
59
|
+
block[4] = (forceZones >> 8) & 0xff;
|
|
60
|
+
block[5] = (forceZones >> 16) & 0xff;
|
|
61
|
+
block[6] = (forceZones >> 24) & 0xff;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
case TriggerEffect.Weapon: {
|
|
65
|
+
const start = Math.min(7, Math.max(2, scale(config.start, 9)));
|
|
66
|
+
const end = Math.min(8, Math.max(start + 1, scale(config.end, 9)));
|
|
67
|
+
const strength = scale(config.strength, 8, 1);
|
|
68
|
+
const startAndStopZones = (1 << start) | (1 << end);
|
|
69
|
+
block[1] = startAndStopZones & 0xff;
|
|
70
|
+
block[2] = (startAndStopZones >> 8) & 0xff;
|
|
71
|
+
block[3] = strength - 1;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case TriggerEffect.Bow: {
|
|
75
|
+
const start = scale(config.start, 8);
|
|
76
|
+
const end = Math.max(start + 1, scale(config.end, 8));
|
|
77
|
+
const strength = scale(config.strength, 8, 1);
|
|
78
|
+
const snapForce = scale(config.snapForce, 8, 1);
|
|
79
|
+
const startAndStopZones = (1 << start) | (1 << end);
|
|
80
|
+
const forcePair = ((strength - 1) & 0x07) | (((snapForce - 1) & 0x07) << 3);
|
|
81
|
+
block[1] = startAndStopZones & 0xff;
|
|
82
|
+
block[2] = (startAndStopZones >> 8) & 0xff;
|
|
83
|
+
block[3] = forcePair & 0xff;
|
|
84
|
+
block[4] = (forcePair >> 8) & 0xff;
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case TriggerEffect.Galloping: {
|
|
88
|
+
const start = scale(config.start, 8);
|
|
89
|
+
const end = Math.max(start + 1, scale(config.end, 9));
|
|
90
|
+
const firstFoot = scale(config.firstFoot, 6);
|
|
91
|
+
const secondFoot = Math.max(firstFoot + 1, scale(config.secondFoot, 7));
|
|
92
|
+
const startAndStopZones = (1 << start) | (1 << end);
|
|
93
|
+
const timeAndRatio = (secondFoot & 0x07) | ((firstFoot & 0x07) << 3);
|
|
94
|
+
block[1] = startAndStopZones & 0xff;
|
|
95
|
+
block[2] = (startAndStopZones >> 8) & 0xff;
|
|
96
|
+
block[3] = timeAndRatio & 0xff;
|
|
97
|
+
block[4] = Math.min(255, Math.max(1, Math.round(config.frequency)));
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
case TriggerEffect.Vibration: {
|
|
101
|
+
const position = scale(config.position, 9);
|
|
102
|
+
const amplitude = scale(config.amplitude, 8, 1);
|
|
103
|
+
const strengthValue = (amplitude - 1) & 0x07;
|
|
104
|
+
let amplitudeZones = 0;
|
|
105
|
+
let activeZones = 0;
|
|
106
|
+
for (let i = position; i < 10; i++) {
|
|
107
|
+
amplitudeZones |= strengthValue << (3 * i);
|
|
108
|
+
activeZones |= 1 << i;
|
|
109
|
+
}
|
|
110
|
+
block[1] = activeZones & 0xff;
|
|
111
|
+
block[2] = (activeZones >> 8) & 0xff;
|
|
112
|
+
block[3] = amplitudeZones & 0xff;
|
|
113
|
+
block[4] = (amplitudeZones >> 8) & 0xff;
|
|
114
|
+
block[5] = (amplitudeZones >> 16) & 0xff;
|
|
115
|
+
block[6] = (amplitudeZones >> 24) & 0xff;
|
|
116
|
+
block[9] = Math.min(255, Math.max(1, Math.round(config.frequency)));
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
case TriggerEffect.Machine: {
|
|
120
|
+
const start = scale(config.start, 8);
|
|
121
|
+
const end = Math.max(start + 1, scale(config.end, 9));
|
|
122
|
+
const amplitudeA = scale(config.amplitudeA, 7);
|
|
123
|
+
const amplitudeB = scale(config.amplitudeB, 7);
|
|
124
|
+
const startAndStopZones = (1 << start) | (1 << end);
|
|
125
|
+
const strengthPair = (amplitudeA & 0x07) | ((amplitudeB & 0x07) << 3);
|
|
126
|
+
block[1] = startAndStopZones & 0xff;
|
|
127
|
+
block[2] = (startAndStopZones >> 8) & 0xff;
|
|
128
|
+
block[3] = strengthPair & 0xff;
|
|
129
|
+
block[4] = Math.min(255, Math.max(1, Math.round(config.frequency)));
|
|
130
|
+
block[5] = Math.round(config.period);
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return block;
|
|
135
|
+
}
|
|
136
|
+
exports.buildTriggerEffectBlock = buildTriggerEffectBlock;
|
|
137
|
+
/** Holds the desired adaptive trigger feedback state and translates it for HID output */
|
|
138
|
+
class TriggerFeedback {
|
|
139
|
+
constructor() {
|
|
140
|
+
this._config = { effect: TriggerEffect.Off };
|
|
141
|
+
}
|
|
142
|
+
/** The current feedback configuration */
|
|
143
|
+
get config() {
|
|
144
|
+
return this._config;
|
|
145
|
+
}
|
|
146
|
+
/** The current effect type */
|
|
147
|
+
get effect() {
|
|
148
|
+
return this._config.effect;
|
|
149
|
+
}
|
|
150
|
+
/** Set adaptive trigger feedback */
|
|
151
|
+
set(config) {
|
|
152
|
+
this._config = config;
|
|
153
|
+
}
|
|
154
|
+
/** Reset to no resistance */
|
|
155
|
+
reset() {
|
|
156
|
+
this._config = { effect: TriggerEffect.Off };
|
|
157
|
+
}
|
|
158
|
+
/** Build the raw 11-byte effect block for HID output */
|
|
159
|
+
toBytes() {
|
|
160
|
+
return buildTriggerEffectBlock(this._config);
|
|
161
|
+
}
|
|
162
|
+
/** String key for change detection in the polling loop */
|
|
163
|
+
toKey() {
|
|
164
|
+
return JSON.stringify(this._config);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.TriggerFeedback = TriggerFeedback;
|
|
168
|
+
//# sourceMappingURL=trigger_feedback.js.map
|