mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-15 17:12:59 -04:00
gumap
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -5,8 +5,8 @@
|
|||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>webui</title>
|
<title>webui</title>
|
||||||
<script type="module" crossorigin src="/assets/index-NGdTJyVK.js"></script>
|
<script type="module" crossorigin src="/assets/index-DFvdwweA.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-ZYHUqx5G.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DxO2_uri.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import AuthPanel from './AuthPanel.jsx';
|
|||||||
import AdminPanel from './AdminPanel.jsx';
|
import AdminPanel from './AdminPanel.jsx';
|
||||||
import KeymapSettings from './KeymapSettings.jsx';
|
import KeymapSettings from './KeymapSettings.jsx';
|
||||||
import InputSettings from './InputSettings.jsx';
|
import InputSettings from './InputSettings.jsx';
|
||||||
|
import GamepadMappingSettings from './GamepadMappingSettings.jsx';
|
||||||
|
|
||||||
const manualTabs = [
|
const manualTabs = [
|
||||||
{ key: 'start', label: 'Start OI' },
|
{ key: 'start', label: 'Start OI' },
|
||||||
@@ -35,7 +36,8 @@ export default function AdvancedSettings() {
|
|||||||
return (
|
return (
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<KeymapSettings />
|
<KeymapSettings />
|
||||||
<InputSettings />
|
{/* <InputSettings /> */}
|
||||||
|
<GamepadMappingSettings />
|
||||||
<section className="rounded-sm bg-[#242a32] p-1 text-sm text-slate-100">
|
<section className="rounded-sm bg-[#242a32] p-1 text-sm text-slate-100">
|
||||||
<p className="text-xs text-slate-400">Manual OI commands</p>
|
<p className="text-xs text-slate-400">Manual OI commands</p>
|
||||||
<div className="mt-1 flex flex-wrap gap-1">
|
<div className="mt-1 flex flex-wrap gap-1">
|
||||||
|
|||||||
@@ -0,0 +1,172 @@
|
|||||||
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
|
import { useSettingsNamespace } from '../settings/index.js';
|
||||||
|
import { GAMEPAD_MAPPING_DEFAULT } from '../settings/namespaces.js';
|
||||||
|
|
||||||
|
function useGamepad() {
|
||||||
|
const [connected, setConnected] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function updateStatus() {
|
||||||
|
const pads = navigator.getGamepads?.();
|
||||||
|
setConnected(Boolean(pads && Array.from(pads).some(Boolean)));
|
||||||
|
}
|
||||||
|
updateStatus();
|
||||||
|
window.addEventListener('gamepadconnected', updateStatus);
|
||||||
|
window.addEventListener('gamepaddisconnected', updateStatus);
|
||||||
|
const id = setInterval(updateStatus, 2000);
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('gamepadconnected', updateStatus);
|
||||||
|
window.removeEventListener('gamepaddisconnected', updateStatus);
|
||||||
|
clearInterval(id);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ACTIONS = [
|
||||||
|
{ id: 'driveHorizontal', label: 'Drive horizontal', type: 'axis', section: 'Drive stick', path: ['drive', 'horizontal'] },
|
||||||
|
{ id: 'driveVertical', label: 'Drive vertical', type: 'axis', section: 'Drive stick', path: ['drive', 'vertical'] },
|
||||||
|
{ id: 'cameraVertical', label: 'Camera vertical', type: 'axis', section: 'Camera stick', path: ['camera', 'vertical'] },
|
||||||
|
{ id: 'mainTrigger', label: 'Main brush trigger', type: 'button', section: 'Brush triggers', path: ['triggers', 'main'] },
|
||||||
|
{ id: 'mainReverse', label: 'Main reverse button', type: 'button', section: 'Brush triggers', path: ['buttons', 'mainReverse'] },
|
||||||
|
{ id: 'sideTrigger', label: 'Side brush trigger', type: 'button', section: 'Brush triggers', path: ['triggers', 'side'] },
|
||||||
|
{ id: 'sideReverse', label: 'Side reverse button', type: 'button', section: 'Brush triggers', path: ['buttons', 'sideReverse'] },
|
||||||
|
{ id: 'vacuum', label: 'Vacuum button', type: 'button', section: 'Auxiliary buttons', path: ['buttons', 'vacuum'] },
|
||||||
|
{ id: 'allAux', label: 'All aux forward button', type: 'button', section: 'Auxiliary buttons', path: ['buttons', 'allAux'] },
|
||||||
|
{ id: 'driveMacro', label: 'Drive macro button', type: 'button', section: 'Mode buttons', path: ['buttons', 'driveMacro'] },
|
||||||
|
{ id: 'dockMacro', label: 'Dock macro button', type: 'button', section: 'Mode buttons', path: ['buttons', 'dockMacro'] },
|
||||||
|
];
|
||||||
|
|
||||||
|
function formatAxis(value) {
|
||||||
|
if (!value) return 'Unassigned';
|
||||||
|
return `Axis ${value.index}${value.invert ? ' (invert)' : ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatButton(value) {
|
||||||
|
if (!value) return 'Unassigned';
|
||||||
|
return `Button ${value.index}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePath(mapping, path, updater) {
|
||||||
|
const [group, key] = path;
|
||||||
|
const next = { ...(mapping ?? GAMEPAD_MAPPING_DEFAULT) };
|
||||||
|
next[group] = { ...(next[group] ?? GAMEPAD_MAPPING_DEFAULT[group]) };
|
||||||
|
next[group][key] = updater(next[group][key]);
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GamepadMappingSettings() {
|
||||||
|
const gamepadConnected = useGamepad();
|
||||||
|
const { value: mapping, save, reset } = useSettingsNamespace('gamepadMapping', GAMEPAD_MAPPING_DEFAULT);
|
||||||
|
const [capture, setCapture] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!capture) return undefined;
|
||||||
|
let raf;
|
||||||
|
const scan = () => {
|
||||||
|
const pads = navigator.getGamepads?.();
|
||||||
|
const pad = pads && Array.from(pads).find(Boolean);
|
||||||
|
if (pad) {
|
||||||
|
if (capture.type === 'axis') {
|
||||||
|
for (let i = 0; i < pad.axes.length; i += 1) {
|
||||||
|
const value = pad.axes[i];
|
||||||
|
if (Math.abs(value) > 0.55) {
|
||||||
|
save((prev) => updatePath(prev, capture.path, () => ({ index: i, invert: value < 0 })));
|
||||||
|
setCapture(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (capture.type === 'button') {
|
||||||
|
for (let i = 0; i < pad.buttons.length; i += 1) {
|
||||||
|
const btn = pad.buttons[i];
|
||||||
|
if (btn && (btn.pressed || btn.value > 0.6)) {
|
||||||
|
save((prev) => updatePath(prev, capture.path, () => ({ index: i })));
|
||||||
|
setCapture(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
raf = requestAnimationFrame(scan);
|
||||||
|
};
|
||||||
|
raf = requestAnimationFrame(scan);
|
||||||
|
return () => {
|
||||||
|
if (raf) cancelAnimationFrame(raf);
|
||||||
|
};
|
||||||
|
}, [capture, save]);
|
||||||
|
|
||||||
|
const grouped = useMemo(() => {
|
||||||
|
return ACTIONS.reduce((acc, action) => {
|
||||||
|
const list = acc[action.section] || (acc[action.section] = []);
|
||||||
|
list.push(action);
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getValueLabel = (action) => {
|
||||||
|
const [group, key] = action.path;
|
||||||
|
const stored = mapping?.[group]?.[key] ?? null;
|
||||||
|
return action.type === 'axis' ? formatAxis(stored) : formatButton(stored);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClear = (action) => {
|
||||||
|
save((prev) => updatePath(prev, action.path, () => null));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="rounded-sm bg-[#1d232b] p-1 text-sm text-slate-100">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-semibold uppercase tracking-wide text-slate-400">Gamepad mapping</p>
|
||||||
|
<p className="text-[0.65rem] text-slate-500">
|
||||||
|
{gamepadConnected ? 'Press buttons or move sticks when prompted.' : 'Connect a controller to configure.'}
|
||||||
|
</p>
|
||||||
|
{capture && (
|
||||||
|
<p className="mt-1 text-[0.7rem] text-emerald-400">Capturing {capture.label}…</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => reset()}
|
||||||
|
className="rounded-sm bg-black/40 px-2 py-1 text-xs uppercase tracking-wide text-slate-200 hover:bg-black/60"
|
||||||
|
>
|
||||||
|
Clear all
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="mt-2 space-y-2">
|
||||||
|
{Object.entries(grouped).map(([section, actions]) => (
|
||||||
|
<div key={section} className="rounded border border-white/5 p-1">
|
||||||
|
<p className="text-[0.7rem] uppercase tracking-wide text-slate-500">{section}</p>
|
||||||
|
<div className="mt-1 space-y-1">
|
||||||
|
{actions.map((action) => (
|
||||||
|
<div key={action.id} className="flex items-center justify-between rounded bg-black/30 px-1 py-1 text-xs">
|
||||||
|
<div>
|
||||||
|
<p className="font-semibold text-slate-100">{action.label}</p>
|
||||||
|
<p className="text-[0.65rem] text-slate-400">{getValueLabel(action)}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleClear(action)}
|
||||||
|
className="rounded bg-slate-800 px-2 py-1 text-[0.65rem] uppercase tracking-wide"
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setCapture(action)}
|
||||||
|
className={`rounded px-2 py-1 text-[0.65rem] uppercase tracking-wide ${capture?.id === action.id ? 'bg-emerald-500 text-emerald-950' : 'bg-slate-700 text-slate-100'}`}
|
||||||
|
>
|
||||||
|
{capture?.id === action.id ? 'Waiting…' : 'Capture'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef } from 'react';
|
|||||||
import { useControlSystem } from '../ControlContext.jsx';
|
import { useControlSystem } from '../ControlContext.jsx';
|
||||||
import { clampUnit } from '../controlMath.js';
|
import { clampUnit } from '../controlMath.js';
|
||||||
import { useSettingsNamespace } from '../../settings/index.js';
|
import { useSettingsNamespace } from '../../settings/index.js';
|
||||||
import { INPUT_SETTINGS_DEFAULTS } from '../../settings/namespaces.js';
|
import { INPUT_SETTINGS_DEFAULTS, GAMEPAD_MAPPING_DEFAULT } from '../../settings/namespaces.js';
|
||||||
|
|
||||||
const SOURCE = 'gamepad';
|
const SOURCE = 'gamepad';
|
||||||
|
|
||||||
@@ -44,25 +44,55 @@ export default function GamepadInputManager() {
|
|||||||
},
|
},
|
||||||
} = useControlSystem();
|
} = useControlSystem();
|
||||||
const { value: inputSettings } = useSettingsNamespace('inputs', INPUT_SETTINGS_DEFAULTS);
|
const { value: inputSettings } = useSettingsNamespace('inputs', INPUT_SETTINGS_DEFAULTS);
|
||||||
|
const { value: mapping } = useSettingsNamespace('gamepadMapping', GAMEPAD_MAPPING_DEFAULT);
|
||||||
const gamepadSettings = inputSettings.gamepad ?? INPUT_SETTINGS_DEFAULTS.gamepad;
|
const gamepadSettings = inputSettings.gamepad ?? INPUT_SETTINGS_DEFAULTS.gamepad;
|
||||||
const driveDeadzone = Math.min(Math.max(gamepadSettings.driveDeadzone ?? 0.2, 0), 0.8);
|
const driveDeadzone = Math.min(Math.max(gamepadSettings.driveDeadzone ?? 0.2, 0), 0.8);
|
||||||
const cameraDeadzone = Math.min(Math.max(gamepadSettings.cameraDeadzone ?? 0.25, 0), 0.9);
|
const cameraDeadzone = Math.min(Math.max(gamepadSettings.cameraDeadzone ?? 0.25, 0), 0.9);
|
||||||
const servoStep = gamepadSettings.servoStep ?? INPUT_SETTINGS_DEFAULTS.gamepad.servoStep;
|
const servoStep = gamepadSettings.servoStep ?? INPUT_SETTINGS_DEFAULTS.gamepad.servoStep;
|
||||||
const auxReverseScale = gamepadSettings.auxReverseScale ?? INPUT_SETTINGS_DEFAULTS.gamepad.auxReverseScale;
|
const auxReverseScale = gamepadSettings.auxReverseScale ?? INPUT_SETTINGS_DEFAULTS.gamepad.auxReverseScale;
|
||||||
|
const mappingReady =
|
||||||
|
Boolean(mapping?.drive?.horizontal) &&
|
||||||
|
Boolean(mapping?.drive?.vertical) &&
|
||||||
|
Boolean(mapping?.camera?.vertical) &&
|
||||||
|
Boolean(mapping?.triggers?.main) &&
|
||||||
|
Boolean(mapping?.triggers?.side) &&
|
||||||
|
Boolean(mapping?.buttons?.mainReverse) &&
|
||||||
|
Boolean(mapping?.buttons?.sideReverse) &&
|
||||||
|
Boolean(mapping?.buttons?.vacuum) &&
|
||||||
|
Boolean(mapping?.buttons?.allAux) &&
|
||||||
|
Boolean(mapping?.buttons?.driveMacro) &&
|
||||||
|
Boolean(mapping?.buttons?.dockMacro);
|
||||||
const rafRef = useRef(null);
|
const rafRef = useRef(null);
|
||||||
const lastVectorRef = useRef({ x: 0, y: 0, boost: false });
|
const lastVectorRef = useRef({ x: 0, y: 0, boost: false });
|
||||||
const lastAuxRef = useRef({ main: 0, side: 0, vacuum: 0 });
|
const lastAuxRef = useRef({ main: 0, side: 0, vacuum: 0 });
|
||||||
const buttonStateRef = useRef(new Map());
|
const buttonStateRef = useRef(new Map());
|
||||||
const servoThrottleRef = useRef(0);
|
const servoThrottleRef = useRef(0);
|
||||||
|
|
||||||
const handleButtonEdge = useCallback(
|
const handleButtonEdge = useCallback((key, pressed) => {
|
||||||
(index, pressed) => {
|
const prev = buttonStateRef.current.get(key) || false;
|
||||||
const prev = buttonStateRef.current.get(index) || false;
|
buttonStateRef.current.set(key, pressed);
|
||||||
buttonStateRef.current.set(index, pressed);
|
return pressed && !prev;
|
||||||
return pressed && !prev;
|
}, []);
|
||||||
},
|
|
||||||
[],
|
const getAxisValue = useCallback((pad, descriptor) => {
|
||||||
);
|
if (!descriptor) return 0;
|
||||||
|
const raw = pad.axes?.[descriptor.index] ?? 0;
|
||||||
|
return descriptor.invert ? -raw : raw;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getButtonValue = useCallback((pad, descriptor) => {
|
||||||
|
if (!descriptor) return 0;
|
||||||
|
const btn = pad.buttons?.[descriptor.index];
|
||||||
|
if (!btn) return 0;
|
||||||
|
return typeof btn.value === 'number' ? btn.value : btn.pressed ? 1 : 0;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const isButtonPressed = useCallback((pad, descriptor) => {
|
||||||
|
if (!descriptor) return false;
|
||||||
|
const btn = pad.buttons?.[descriptor.index];
|
||||||
|
if (!btn) return false;
|
||||||
|
return btn.pressed || btn.value > 0.5;
|
||||||
|
}, []);
|
||||||
|
|
||||||
const pollGamepads = useCallback(() => {
|
const pollGamepads = useCallback(() => {
|
||||||
if (typeof navigator === 'undefined' || !navigator.getGamepads) {
|
if (typeof navigator === 'undefined' || !navigator.getGamepads) {
|
||||||
@@ -79,23 +109,34 @@ export default function GamepadInputManager() {
|
|||||||
lastAuxRef.current = { main: 0, side: 0, vacuum: 0 };
|
lastAuxRef.current = { main: 0, side: 0, vacuum: 0 };
|
||||||
setAuxMotors({ main: 0, side: 0, vacuum: 0 });
|
setAuxMotors({ main: 0, side: 0, vacuum: 0 });
|
||||||
}
|
}
|
||||||
registerInputState(SOURCE, { connected: false });
|
registerInputState(SOURCE, { connected: false, mappingReady });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const axisLX = clampUnit(applyDeadzone(pad.axes?.[0] ?? 0, driveDeadzone));
|
if (!mappingReady) {
|
||||||
const axisLY = clampUnit(applyDeadzone(-(pad.axes?.[1] ?? 0), driveDeadzone));
|
registerInputState(SOURCE, { connected: true, mappingReady: false });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const axisLX = clampUnit(applyDeadzone(getAxisValue(pad, mapping.drive.horizontal), driveDeadzone));
|
||||||
|
const axisLY = clampUnit(applyDeadzone(-getAxisValue(pad, mapping.drive.vertical), driveDeadzone));
|
||||||
const vector = { x: axisLX, y: axisLY, boost: false };
|
const vector = { x: axisLX, y: axisLY, boost: false };
|
||||||
if (!vectorsEqual(vector, lastVectorRef.current)) {
|
if (!vectorsEqual(vector, lastVectorRef.current)) {
|
||||||
lastVectorRef.current = vector;
|
lastVectorRef.current = vector;
|
||||||
setDriveVector(vector, { source: SOURCE });
|
setDriveVector(vector, { source: SOURCE });
|
||||||
}
|
}
|
||||||
|
|
||||||
const main = computeTriggerSpeed(pad.buttons?.[7], pad.buttons?.[5]);
|
const mainMagnitude = Math.round(getButtonValue(pad, mapping.triggers.main) * 127);
|
||||||
const side = computeTriggerSpeed(pad.buttons?.[6], pad.buttons?.[4], 127, auxReverseScale);
|
const mainReverse = isButtonPressed(pad, mapping.buttons.mainReverse);
|
||||||
const vacuum = pad.buttons?.[1]?.pressed ? 127 : 0;
|
const main = mainReverse ? -mainMagnitude : mainMagnitude;
|
||||||
|
|
||||||
|
const sideMagnitude = Math.round(getButtonValue(pad, mapping.triggers.side) * 127);
|
||||||
|
const sideReverse = isButtonPressed(pad, mapping.buttons.sideReverse);
|
||||||
|
const side = sideReverse ? -Math.round(sideMagnitude * auxReverseScale) : sideMagnitude;
|
||||||
|
|
||||||
|
const vacuum = isButtonPressed(pad, mapping.buttons.vacuum) ? 127 : 0;
|
||||||
let aux = { main, side, vacuum };
|
let aux = { main, side, vacuum };
|
||||||
if (pad.buttons?.[0]?.pressed) {
|
if (isButtonPressed(pad, mapping.buttons.allAux)) {
|
||||||
aux = { main: 127, side: 127, vacuum: 127 };
|
aux = { main: 127, side: 127, vacuum: 127 };
|
||||||
}
|
}
|
||||||
if (!auxEqual(aux, lastAuxRef.current)) {
|
if (!auxEqual(aux, lastAuxRef.current)) {
|
||||||
@@ -103,18 +144,20 @@ export default function GamepadInputManager() {
|
|||||||
setAuxMotors(aux);
|
setAuxMotors(aux);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cameraAxis = clampUnit(applyDeadzone(-(pad.axes?.[3] ?? 0), cameraDeadzone));
|
const cameraAxis = clampUnit(applyDeadzone(-getAxisValue(pad, mapping.camera.vertical), cameraDeadzone));
|
||||||
const now = performance.now();
|
const now = performance.now();
|
||||||
if (Math.abs(cameraAxis) > 0.25 && now - servoThrottleRef.current > 120) {
|
if (Math.abs(cameraAxis) > 0.25 && now - servoThrottleRef.current > 120) {
|
||||||
servoThrottleRef.current = now;
|
servoThrottleRef.current = now;
|
||||||
nudgeServo(cameraAxis > 0 ? servoStep : -servoStep);
|
nudgeServo(cameraAxis > 0 ? servoStep : -servoStep);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handleButtonEdge(14, pad.buttons?.[14]?.pressed)) {
|
const driveMacroPressed = isButtonPressed(pad, mapping.buttons.driveMacro);
|
||||||
|
if (handleButtonEdge(`macro-${mapping.buttons.driveMacro.index}`, driveMacroPressed)) {
|
||||||
setMode('drive');
|
setMode('drive');
|
||||||
runMacro('drive-sequence');
|
runMacro('drive-sequence');
|
||||||
}
|
}
|
||||||
if (handleButtonEdge(15, pad.buttons?.[15]?.pressed)) {
|
const dockMacroPressed = isButtonPressed(pad, mapping.buttons.dockMacro);
|
||||||
|
if (handleButtonEdge(`macro-${mapping.buttons.dockMacro.index}`, dockMacroPressed)) {
|
||||||
setMode('dock');
|
setMode('dock');
|
||||||
runMacro('seek-dock');
|
runMacro('seek-dock');
|
||||||
}
|
}
|
||||||
@@ -135,7 +178,22 @@ export default function GamepadInputManager() {
|
|||||||
auxReverseScale,
|
auxReverseScale,
|
||||||
cameraDeadzone,
|
cameraDeadzone,
|
||||||
driveDeadzone,
|
driveDeadzone,
|
||||||
|
getAxisValue,
|
||||||
|
getButtonValue,
|
||||||
handleButtonEdge,
|
handleButtonEdge,
|
||||||
|
isButtonPressed,
|
||||||
|
mapping.buttons?.allAux,
|
||||||
|
mapping.buttons?.dockMacro,
|
||||||
|
mapping.buttons?.driveMacro,
|
||||||
|
mapping.buttons?.mainReverse,
|
||||||
|
mapping.buttons?.sideReverse,
|
||||||
|
mapping.buttons?.vacuum,
|
||||||
|
mapping.camera?.vertical,
|
||||||
|
mapping.drive?.horizontal,
|
||||||
|
mapping.drive?.vertical,
|
||||||
|
mapping.triggers?.main,
|
||||||
|
mapping.triggers?.side,
|
||||||
|
mappingReady,
|
||||||
nudgeServo,
|
nudgeServo,
|
||||||
registerInputState,
|
registerInputState,
|
||||||
runMacro,
|
runMacro,
|
||||||
|
|||||||
@@ -10,3 +10,25 @@ export const INPUT_SETTINGS_DEFAULTS = {
|
|||||||
joystickSmoothing: 0.15,
|
joystickSmoothing: 0.15,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const GAMEPAD_MAPPING_DEFAULT = {
|
||||||
|
drive: {
|
||||||
|
horizontal: null,
|
||||||
|
vertical: null,
|
||||||
|
},
|
||||||
|
camera: {
|
||||||
|
vertical: null,
|
||||||
|
},
|
||||||
|
triggers: {
|
||||||
|
main: null,
|
||||||
|
side: null,
|
||||||
|
},
|
||||||
|
buttons: {
|
||||||
|
mainReverse: null,
|
||||||
|
sideReverse: null,
|
||||||
|
vacuum: null,
|
||||||
|
allAux: null,
|
||||||
|
driveMacro: null,
|
||||||
|
dockMacro: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user