@kelnishi/satmouse-client 0.9.12 → 0.9.13
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/dist/chunk-I47ZOX3M.js +64 -0
- package/dist/chunk-I47ZOX3M.js.map +1 -0
- package/dist/chunk-LDSDVYCV.cjs +69 -0
- package/dist/chunk-LDSDVYCV.cjs.map +1 -0
- package/dist/{connection-CH2YsPn1.d.cts → connection-5KQFvHoJ.d.cts} +8 -1
- package/dist/{connection-CH2YsPn1.d.ts → connection-5KQFvHoJ.d.ts} +8 -1
- package/dist/core/index.cjs +16 -0
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +2 -2
- package/dist/core/index.d.ts +2 -2
- package/dist/core/index.js +16 -0
- package/dist/core/index.js.map +1 -1
- package/dist/elements/index.cjs +301 -0
- package/dist/elements/index.cjs.map +1 -0
- package/dist/elements/index.d.cts +35 -0
- package/dist/elements/index.d.ts +35 -0
- package/dist/elements/index.js +295 -0
- package/dist/elements/index.js.map +1 -0
- package/dist/react/index.cjs +56 -19
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +13 -3
- package/dist/react/index.d.ts +13 -3
- package/dist/react/index.js +56 -19
- package/dist/react/index.js.map +1 -1
- package/dist/utils/index.cjs +60 -87
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +6 -3
- package/dist/utils/index.d.ts +6 -3
- package/dist/utils/index.js +43 -81
- package/dist/utils/index.js.map +1 -1
- package/package.json +9 -3
package/dist/react/index.d.ts
CHANGED
|
@@ -21,6 +21,8 @@ interface SpatialData {
|
|
|
21
21
|
translation: Vec3;
|
|
22
22
|
rotation: Vec3;
|
|
23
23
|
timestamp: number;
|
|
24
|
+
/** Source device ID (e.g., "cnx-c635", "hid-054c-5c4") */
|
|
25
|
+
deviceId?: string;
|
|
24
26
|
}
|
|
25
27
|
/** Button press/release event — matches button-event.schema.json */
|
|
26
28
|
interface ButtonEvent {
|
|
@@ -39,7 +41,7 @@ interface DeviceInfo$1 {
|
|
|
39
41
|
connectionType?: "usb" | "wireless" | "bluetooth" | "unknown";
|
|
40
42
|
connected?: boolean;
|
|
41
43
|
}
|
|
42
|
-
type ConnectionState = "disconnected" | "connecting" | "connected";
|
|
44
|
+
type ConnectionState = "disconnected" | "connecting" | "connected" | "failed";
|
|
43
45
|
type TransportProtocol = "webtransport" | "websocket" | "none";
|
|
44
46
|
interface SatMouseEvents {
|
|
45
47
|
spatialData: (data: SpatialData) => void;
|
|
@@ -67,6 +69,8 @@ interface ConnectOptions {
|
|
|
67
69
|
transports?: TransportProtocol[];
|
|
68
70
|
/** Auto-reconnect delay in ms. 0 to disable. Default: 2000 */
|
|
69
71
|
reconnectDelay?: number;
|
|
72
|
+
/** Max reconnect attempts before giving up. Default: 3 */
|
|
73
|
+
maxRetries?: number;
|
|
70
74
|
/** WebSocket subprotocol. Default: "satmouse-json" */
|
|
71
75
|
wsSubprotocol?: "satmouse-json" | "satmouse-binary";
|
|
72
76
|
}
|
|
@@ -83,12 +87,15 @@ declare class SatMouseConnection extends TypedEmitter<SatMouseEvents> {
|
|
|
83
87
|
private reconnectTimer;
|
|
84
88
|
private intentionalClose;
|
|
85
89
|
private deviceInfoUrl;
|
|
90
|
+
private retryCount;
|
|
86
91
|
private _state;
|
|
87
92
|
private _protocol;
|
|
88
93
|
get state(): ConnectionState;
|
|
89
94
|
get protocol(): TransportProtocol;
|
|
90
95
|
constructor(options?: ConnectOptions);
|
|
91
96
|
connect(): Promise<void>;
|
|
97
|
+
/** Reset retry count and reconnect. Use after "failed" state. */
|
|
98
|
+
retry(): void;
|
|
92
99
|
disconnect(): void;
|
|
93
100
|
fetchDeviceInfo(): Promise<DeviceInfo$1[]>;
|
|
94
101
|
private tryTransport;
|
|
@@ -212,7 +219,7 @@ declare class InputManager extends TypedEmitter<InputManagerEvents> {
|
|
|
212
219
|
private connections;
|
|
213
220
|
private storage?;
|
|
214
221
|
private knownDevices;
|
|
215
|
-
private
|
|
222
|
+
private deviceAccumulators;
|
|
216
223
|
private accDirty;
|
|
217
224
|
private flushTimer;
|
|
218
225
|
private _config;
|
|
@@ -244,7 +251,10 @@ declare class InputManager extends TypedEmitter<InputManagerEvents> {
|
|
|
244
251
|
onActionValues(callback: (values: ActionValues) => void): () => void;
|
|
245
252
|
private wireConnection;
|
|
246
253
|
private flushAccumulator;
|
|
247
|
-
|
|
254
|
+
/** Per-device transforms: flip, sensitivity, dead zone, dominant, axis remap */
|
|
255
|
+
private processPerDevice;
|
|
256
|
+
/** Global transforms applied after per-device merge: locks + action map */
|
|
257
|
+
private applyGlobalTransforms;
|
|
248
258
|
}
|
|
249
259
|
|
|
250
260
|
interface SatMouseContextValue {
|
package/dist/react/index.js
CHANGED
|
@@ -267,6 +267,7 @@ function parseSatMouseUri(uri) {
|
|
|
267
267
|
var DEFAULT_OPTIONS = {
|
|
268
268
|
transports: ["webtransport", "websocket"],
|
|
269
269
|
reconnectDelay: 2e3,
|
|
270
|
+
maxRetries: 3,
|
|
270
271
|
wsSubprotocol: "satmouse-json"
|
|
271
272
|
};
|
|
272
273
|
var SatMouseConnection = class extends TypedEmitter {
|
|
@@ -275,6 +276,7 @@ var SatMouseConnection = class extends TypedEmitter {
|
|
|
275
276
|
reconnectTimer = null;
|
|
276
277
|
intentionalClose = false;
|
|
277
278
|
deviceInfoUrl = null;
|
|
279
|
+
retryCount = 0;
|
|
278
280
|
_state = "disconnected";
|
|
279
281
|
_protocol = "none";
|
|
280
282
|
get state() {
|
|
@@ -335,6 +337,12 @@ var SatMouseConnection = class extends TypedEmitter {
|
|
|
335
337
|
this.setState("disconnected", "none");
|
|
336
338
|
this.scheduleReconnect();
|
|
337
339
|
}
|
|
340
|
+
/** Reset retry count and reconnect. Use after "failed" state. */
|
|
341
|
+
retry() {
|
|
342
|
+
this.retryCount = 0;
|
|
343
|
+
this.intentionalClose = false;
|
|
344
|
+
this.connect();
|
|
345
|
+
}
|
|
338
346
|
disconnect() {
|
|
339
347
|
this.intentionalClose = true;
|
|
340
348
|
this.clearReconnect();
|
|
@@ -366,6 +374,7 @@ var SatMouseConnection = class extends TypedEmitter {
|
|
|
366
374
|
try {
|
|
367
375
|
await adapter.connect();
|
|
368
376
|
this.transport = adapter;
|
|
377
|
+
this.retryCount = 0;
|
|
369
378
|
this.setState("connected", adapter.protocol);
|
|
370
379
|
return true;
|
|
371
380
|
} catch (err) {
|
|
@@ -381,6 +390,13 @@ var SatMouseConnection = class extends TypedEmitter {
|
|
|
381
390
|
}
|
|
382
391
|
scheduleReconnect() {
|
|
383
392
|
if (this.options.reconnectDelay <= 0 || this.intentionalClose) return;
|
|
393
|
+
this.retryCount++;
|
|
394
|
+
console.log(`[SatMouse] Reconnect attempt ${this.retryCount}/${this.options.maxRetries}`);
|
|
395
|
+
if (this.retryCount > this.options.maxRetries) {
|
|
396
|
+
console.log("[SatMouse] Max retries exceeded, giving up");
|
|
397
|
+
this.setState("failed", "none");
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
384
400
|
this.clearReconnect();
|
|
385
401
|
this.reconnectTimer = setTimeout(() => {
|
|
386
402
|
this.reconnectTimer = null;
|
|
@@ -479,14 +495,17 @@ function actionValuesToSpatialData(values, timestamp) {
|
|
|
479
495
|
// src/utils/config.ts
|
|
480
496
|
var DEFAULT_CONFIG = {
|
|
481
497
|
sensitivity: { translation: 1e-3, rotation: 1e-3 },
|
|
482
|
-
flip: { tx: false, ty:
|
|
498
|
+
flip: { tx: false, ty: false, tz: false, rx: false, ry: false, rz: false },
|
|
483
499
|
deadZone: 0,
|
|
484
500
|
dominant: false,
|
|
485
501
|
axisRemap: { tx: "x", ty: "y", tz: "z", rx: "x", ry: "y", rz: "z" },
|
|
486
502
|
lockPosition: false,
|
|
487
503
|
lockRotation: false,
|
|
488
504
|
actionMap: { ...DEFAULT_ACTION_MAP },
|
|
489
|
-
devices: {
|
|
505
|
+
devices: {
|
|
506
|
+
// SpaceMouse Z-up → Three.js Y-up axis correction
|
|
507
|
+
"cnx-*": { flip: { ty: true, tz: true, ry: true, rz: true } }
|
|
508
|
+
}
|
|
490
509
|
};
|
|
491
510
|
function mergeConfig(base, partial) {
|
|
492
511
|
const merged = {
|
|
@@ -650,8 +669,8 @@ var InputManager = class extends TypedEmitter {
|
|
|
650
669
|
connections = [];
|
|
651
670
|
storage;
|
|
652
671
|
knownDevices = /* @__PURE__ */ new Map();
|
|
653
|
-
//
|
|
654
|
-
|
|
672
|
+
// Per-device accumulators: latest value from each device per frame tick
|
|
673
|
+
deviceAccumulators = /* @__PURE__ */ new Map();
|
|
655
674
|
accDirty = false;
|
|
656
675
|
flushTimer = null;
|
|
657
676
|
_config;
|
|
@@ -749,13 +768,16 @@ var InputManager = class extends TypedEmitter {
|
|
|
749
768
|
wireConnection(connection) {
|
|
750
769
|
connection.on("spatialData", (raw) => {
|
|
751
770
|
this.emit("rawSpatialData", raw);
|
|
752
|
-
const
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
771
|
+
const id = raw.deviceId ?? "_default";
|
|
772
|
+
const processed = this.processPerDevice(raw, id);
|
|
773
|
+
this.deviceAccumulators.set(id, {
|
|
774
|
+
tx: processed.translation.x,
|
|
775
|
+
ty: processed.translation.y,
|
|
776
|
+
tz: processed.translation.z,
|
|
777
|
+
rx: processed.rotation.x,
|
|
778
|
+
ry: processed.rotation.y,
|
|
779
|
+
rz: processed.rotation.z
|
|
780
|
+
});
|
|
759
781
|
this.accDirty = true;
|
|
760
782
|
});
|
|
761
783
|
connection.on("buttonEvent", (event) => this.emit("buttonEvent", event));
|
|
@@ -768,25 +790,40 @@ var InputManager = class extends TypedEmitter {
|
|
|
768
790
|
}
|
|
769
791
|
flushAccumulator() {
|
|
770
792
|
if (!this.accDirty) return;
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
|
|
793
|
+
const merged = { tx: 0, ty: 0, tz: 0, rx: 0, ry: 0, rz: 0 };
|
|
794
|
+
for (const acc of this.deviceAccumulators.values()) {
|
|
795
|
+
merged.tx += acc.tx;
|
|
796
|
+
merged.ty += acc.ty;
|
|
797
|
+
merged.tz += acc.tz;
|
|
798
|
+
merged.rx += acc.rx;
|
|
799
|
+
merged.ry += acc.ry;
|
|
800
|
+
merged.rz += acc.rz;
|
|
801
|
+
}
|
|
802
|
+
this.deviceAccumulators.clear();
|
|
803
|
+
this.accDirty = false;
|
|
804
|
+
const data = {
|
|
805
|
+
translation: { x: merged.tx, y: merged.ty, z: merged.tz },
|
|
806
|
+
rotation: { x: merged.rx, y: merged.ry, z: merged.rz },
|
|
774
807
|
timestamp: performance.now() * 1e3
|
|
775
808
|
};
|
|
776
|
-
|
|
777
|
-
this.accDirty = false;
|
|
778
|
-
const { spatial, actions } = this.processSpatialData(raw);
|
|
809
|
+
const { spatial, actions } = this.applyGlobalTransforms(data);
|
|
779
810
|
if (spatial) this.emit("spatialData", spatial);
|
|
780
811
|
if (actions) this.emit("actionValues", actions);
|
|
781
812
|
}
|
|
782
|
-
|
|
783
|
-
|
|
813
|
+
/** Per-device transforms: flip, sensitivity, dead zone, dominant, axis remap */
|
|
814
|
+
processPerDevice(raw, deviceId) {
|
|
815
|
+
const cfg = resolveDeviceConfig(this._config, deviceId);
|
|
784
816
|
let data = raw;
|
|
785
817
|
if (cfg.deadZone > 0) data = applyDeadZone(data, cfg.deadZone);
|
|
786
818
|
if (cfg.dominant) data = applyDominant(data);
|
|
787
819
|
data = applyFlip(data, cfg.flip);
|
|
788
820
|
data = applyAxisRemap(data, cfg.axisRemap);
|
|
789
821
|
data = applySensitivity(data, cfg.sensitivity);
|
|
822
|
+
return data;
|
|
823
|
+
}
|
|
824
|
+
/** Global transforms applied after per-device merge: locks + action map */
|
|
825
|
+
applyGlobalTransforms(data) {
|
|
826
|
+
const cfg = this._config;
|
|
790
827
|
if (cfg.lockPosition) {
|
|
791
828
|
data = { ...data, translation: { x: 0, y: 0, z: 0 } };
|
|
792
829
|
}
|