@kelnishi/satmouse-client 0.9.9 → 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 +71 -7
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +16 -2
- package/dist/react/index.d.ts +16 -2
- package/dist/react/index.js +71 -7
- package/dist/react/index.js.map +1 -1
- package/dist/utils/index.cjs +75 -75
- package/dist/utils/index.cjs.map +1 -1
- package/dist/utils/index.d.cts +9 -2
- package/dist/utils/index.d.ts +9 -2
- package/dist/utils/index.js +58 -69
- 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,6 +219,9 @@ declare class InputManager extends TypedEmitter<InputManagerEvents> {
|
|
|
212
219
|
private connections;
|
|
213
220
|
private storage?;
|
|
214
221
|
private knownDevices;
|
|
222
|
+
private deviceAccumulators;
|
|
223
|
+
private accDirty;
|
|
224
|
+
private flushTimer;
|
|
215
225
|
private _config;
|
|
216
226
|
get config(): InputConfig;
|
|
217
227
|
constructor(config?: Partial<InputConfig>, storage?: StorageAdapter);
|
|
@@ -240,7 +250,11 @@ declare class InputManager extends TypedEmitter<InputManagerEvents> {
|
|
|
240
250
|
/** Register a callback for action values. Returns unsubscribe function. */
|
|
241
251
|
onActionValues(callback: (values: ActionValues) => void): () => void;
|
|
242
252
|
private wireConnection;
|
|
243
|
-
private
|
|
253
|
+
private flushAccumulator;
|
|
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;
|
|
244
258
|
}
|
|
245
259
|
|
|
246
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,6 +669,10 @@ var InputManager = class extends TypedEmitter {
|
|
|
650
669
|
connections = [];
|
|
651
670
|
storage;
|
|
652
671
|
knownDevices = /* @__PURE__ */ new Map();
|
|
672
|
+
// Per-device accumulators: latest value from each device per frame tick
|
|
673
|
+
deviceAccumulators = /* @__PURE__ */ new Map();
|
|
674
|
+
accDirty = false;
|
|
675
|
+
flushTimer = null;
|
|
653
676
|
_config;
|
|
654
677
|
get config() {
|
|
655
678
|
return this._config;
|
|
@@ -659,6 +682,7 @@ var InputManager = class extends TypedEmitter {
|
|
|
659
682
|
this.storage = storage;
|
|
660
683
|
const persisted = loadSettings(storage);
|
|
661
684
|
this._config = mergeConfig(DEFAULT_CONFIG, { ...config, ...persisted });
|
|
685
|
+
this.flushTimer = setInterval(() => this.flushAccumulator(), 16);
|
|
662
686
|
}
|
|
663
687
|
/** Add a connection to the managed set */
|
|
664
688
|
addConnection(connection) {
|
|
@@ -678,6 +702,10 @@ var InputManager = class extends TypedEmitter {
|
|
|
678
702
|
/** Disconnect all managed connections */
|
|
679
703
|
disconnect() {
|
|
680
704
|
for (const c of this.connections) c.disconnect();
|
|
705
|
+
if (this.flushTimer) {
|
|
706
|
+
clearInterval(this.flushTimer);
|
|
707
|
+
this.flushTimer = null;
|
|
708
|
+
}
|
|
681
709
|
}
|
|
682
710
|
/** Fetch device info from all connections */
|
|
683
711
|
async fetchDeviceInfo() {
|
|
@@ -740,9 +768,17 @@ var InputManager = class extends TypedEmitter {
|
|
|
740
768
|
wireConnection(connection) {
|
|
741
769
|
connection.on("spatialData", (raw) => {
|
|
742
770
|
this.emit("rawSpatialData", raw);
|
|
743
|
-
const
|
|
744
|
-
|
|
745
|
-
|
|
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
|
+
});
|
|
781
|
+
this.accDirty = true;
|
|
746
782
|
});
|
|
747
783
|
connection.on("buttonEvent", (event) => this.emit("buttonEvent", event));
|
|
748
784
|
connection.on("stateChange", (state, proto) => this.emit("stateChange", state, proto));
|
|
@@ -752,14 +788,42 @@ var InputManager = class extends TypedEmitter {
|
|
|
752
788
|
this.emit("deviceStatus", event, device);
|
|
753
789
|
});
|
|
754
790
|
}
|
|
755
|
-
|
|
756
|
-
|
|
791
|
+
flushAccumulator() {
|
|
792
|
+
if (!this.accDirty) return;
|
|
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 },
|
|
807
|
+
timestamp: performance.now() * 1e3
|
|
808
|
+
};
|
|
809
|
+
const { spatial, actions } = this.applyGlobalTransforms(data);
|
|
810
|
+
if (spatial) this.emit("spatialData", spatial);
|
|
811
|
+
if (actions) this.emit("actionValues", actions);
|
|
812
|
+
}
|
|
813
|
+
/** Per-device transforms: flip, sensitivity, dead zone, dominant, axis remap */
|
|
814
|
+
processPerDevice(raw, deviceId) {
|
|
815
|
+
const cfg = resolveDeviceConfig(this._config, deviceId);
|
|
757
816
|
let data = raw;
|
|
758
817
|
if (cfg.deadZone > 0) data = applyDeadZone(data, cfg.deadZone);
|
|
759
818
|
if (cfg.dominant) data = applyDominant(data);
|
|
760
819
|
data = applyFlip(data, cfg.flip);
|
|
761
820
|
data = applyAxisRemap(data, cfg.axisRemap);
|
|
762
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;
|
|
763
827
|
if (cfg.lockPosition) {
|
|
764
828
|
data = { ...data, translation: { x: 0, y: 0, z: 0 } };
|
|
765
829
|
}
|