Compare commits
7 Commits
main
...
controller
Author | SHA1 | Date |
---|---|---|
Bit Borealis | 3ea6bf0466 | |
Bit Borealis | 2d46d98c77 | |
Bit Borealis | 3696373dfc | |
Bailey Stevens | 72bc8ec5f2 | |
Bailey Stevens | 8712bcdde1 | |
Bailey Stevens | 1314800b25 | |
Bailey Stevens | 47fd696e6f |
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"recommendations": [
|
||||
"biomejs.biome",
|
||||
"jnoortheen.nix-ide",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"ms-python.vscode-pylance"
|
||||
]
|
||||
}
|
|
@ -33,7 +33,7 @@
|
|||
"type": "node-terminal",
|
||||
"name": "Serve",
|
||||
"request": "launch",
|
||||
"command": "npm run serve -- --no-client-overlay",
|
||||
"command": "npm run serve -- --no-client",
|
||||
"cwd": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -3,14 +3,15 @@
|
|||
import argparse
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from collections import namedtuple
|
||||
from functools import partial
|
||||
|
||||
import websockets
|
||||
from .mmelodies_pb2 import UpdateRequest, Update, Parameter
|
||||
from .mmelodies_pb2 import UpdateRequest, Update
|
||||
|
||||
|
||||
CONNECTIONS = {}
|
||||
|
||||
|
||||
def connections(*paths):
|
||||
if not paths:
|
||||
paths = CONNECTIONS.keys()
|
||||
|
@ -19,7 +20,7 @@ def connections(*paths):
|
|||
for path in paths:
|
||||
clients.extend(CONNECTIONS.get(path, []))
|
||||
|
||||
return clients
|
||||
return clients
|
||||
|
||||
|
||||
async def request_handler(ws, writer):
|
||||
|
@ -41,11 +42,12 @@ async def request_handler(ws, writer):
|
|||
writer.write(b"scope;")
|
||||
if request.param_refresh:
|
||||
writer.write(b"params;")
|
||||
if request.pgm_event:
|
||||
writer.write(f"pgmevt {request.pgm_event};".encode())
|
||||
|
||||
for param in request.param_changes:
|
||||
writer.write(f"set {param.id} {param.value};".encode())
|
||||
|
||||
|
||||
writer.write(b"\n")
|
||||
|
||||
await writer.drain()
|
||||
|
@ -94,7 +96,6 @@ async def update_handler(reader):
|
|||
websockets.broadcast(clients, update.SerializeToString())
|
||||
except Exception as e:
|
||||
print(repr(e))
|
||||
|
||||
|
||||
|
||||
async def _main(listen_port, pd_port):
|
||||
|
@ -143,7 +144,7 @@ async def _main(listen_port, pd_port):
|
|||
|
||||
async with ws:
|
||||
while True:
|
||||
await update_handler(pd_reader)
|
||||
await update_handler(pd_reader)
|
||||
|
||||
|
||||
def port(arg: str):
|
||||
|
|
|
@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
|
|||
|
||||
|
||||
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fmmelodies.proto\"&\n\tParameter\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r\"\x8e\x01\n\rUpdateRequest\x12\x1a\n\rscope_samples\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1a\n\rparam_refresh\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12!\n\rparam_changes\x18\x02 \x03(\x0b\x32\n.ParameterB\x10\n\x0e_scope_samplesB\x10\n\x0e_param_refresh\";\n\x06Update\x12\x15\n\rscope_samples\x18\x01 \x03(\x02\x12\x1a\n\x06params\x18\x02 \x03(\x0b\x32\n.Parameterb\x06proto3')
|
||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fmmelodies.proto\"&\n\tParameter\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05value\x18\x02 \x01(\r\"\xb4\x01\n\rUpdateRequest\x12\x1a\n\rscope_samples\x18\x01 \x01(\x08H\x00\x88\x01\x01\x12\x1a\n\rparam_refresh\x18\x03 \x01(\x08H\x01\x88\x01\x01\x12\x16\n\tpgm_event\x18\x04 \x01(\rH\x02\x88\x01\x01\x12!\n\rparam_changes\x18\x02 \x03(\x0b\x32\n.ParameterB\x10\n\x0e_scope_samplesB\x10\n\x0e_param_refreshB\x0c\n\n_pgm_event\";\n\x06Update\x12\x15\n\rscope_samples\x18\x01 \x03(\x02\x12\x1a\n\x06params\x18\x02 \x03(\x0b\x32\n.Parameterb\x06proto3')
|
||||
|
||||
|
||||
|
||||
|
@ -48,7 +48,7 @@ if _descriptor._USE_C_DESCRIPTORS == False:
|
|||
_PARAMETER._serialized_start=19
|
||||
_PARAMETER._serialized_end=57
|
||||
_UPDATEREQUEST._serialized_start=60
|
||||
_UPDATEREQUEST._serialized_end=202
|
||||
_UPDATE._serialized_start=204
|
||||
_UPDATE._serialized_end=263
|
||||
_UPDATEREQUEST._serialized_end=240
|
||||
_UPDATE._serialized_start=242
|
||||
_UPDATE._serialized_end=301
|
||||
# @@protoc_insertion_point(module_scope)
|
||||
|
|
|
@ -96,11 +96,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1696434240,
|
||||
"narHash": "sha256-DDOn4JmDfl7GkWIsFMF9puGSmJvAO1x1t2rQIYg+DTQ=",
|
||||
"lastModified": 1696489753,
|
||||
"narHash": "sha256-7o3sAmftK9KGoAD4d3UPg9hveviT5fgQA42u+3DUclQ=",
|
||||
"ref": "refs/heads/main",
|
||||
"rev": "e36c08b5291c38796494b7d0c17d190f097f18a7",
|
||||
"revCount": 25,
|
||||
"rev": "728d931a877c7324bd652ebcdd9dfe63f7f1d596",
|
||||
"revCount": 26,
|
||||
"type": "git",
|
||||
"url": "https://fem.mint.lgbt/mmelodies/phyzzy.git"
|
||||
},
|
||||
|
|
|
@ -8,6 +8,7 @@ message Parameter {
|
|||
message UpdateRequest {
|
||||
optional bool scope_samples = 1;
|
||||
optional bool param_refresh = 3;
|
||||
optional uint32 pgm_event = 4;
|
||||
repeated Parameter param_changes = 2;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,3 +18,19 @@ h3 {
|
|||
.combo-switch [type=range] {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#gyroBox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#accelBox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#orientBox {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#unsupported-warning {
|
||||
display: none;
|
||||
}
|
|
@ -38,11 +38,26 @@ h1 {
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
.warning {
|
||||
background-color: var(--secondary);
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
font-weight: bold;
|
||||
margin: auto;
|
||||
width: 75%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.button-box a:focus {
|
||||
border: 15px solid var(--foreground);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: center;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--background);
|
||||
font-family: sans-serif;
|
||||
|
|
|
@ -16,7 +16,7 @@ function connect_ws() {
|
|||
ws.binaryType = "arraybuffer";
|
||||
|
||||
ws.addEventListener("open", () => {
|
||||
const message = UpdateRequest.create({ paramRefresh: true});
|
||||
const message = UpdateRequest.create({ paramRefresh: true });
|
||||
const request = UpdateRequest.encode(message).finish();
|
||||
if (socket) {
|
||||
socket.send(request);
|
||||
|
@ -63,197 +63,111 @@ sliders.forEach((slider, i) => {
|
|||
});
|
||||
});
|
||||
|
||||
// Select all checkbox input elements
|
||||
const switches = document.querySelectorAll(
|
||||
"input[type=checkbox]",
|
||||
) as NodeListOf<HTMLInputElement>;
|
||||
|
||||
// Add an event listener to each switch
|
||||
switches.forEach((switchElement) => {
|
||||
switchElement.addEventListener("change", function () {
|
||||
console.log(`Switch ${this.id} state: ${this.checked}`);
|
||||
});
|
||||
});
|
||||
|
||||
// Declare a global interface for the window object
|
||||
declare global {
|
||||
interface Window {
|
||||
Accelerometer: any;
|
||||
Gyroscope: any;
|
||||
AbsoluteOrientationSensor: any;
|
||||
}
|
||||
}
|
||||
|
||||
if (window.AbsoluteOrientationSensor) {
|
||||
const sensor = new window.AbsoluteOrientationSensor();
|
||||
// Show elements hidden by default
|
||||
function show(element: HTMLElement) {
|
||||
if (element) {
|
||||
element.style.display = "flex";
|
||||
}
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
// @ts-ignore
|
||||
navigator.permissions.query({ name: "accelerometer" }),
|
||||
// @ts-ignore
|
||||
navigator.permissions.query({ name: "magnetometer" }),
|
||||
// @ts-ignore
|
||||
navigator.permissions.query({ name: "gyroscope" }),
|
||||
]).then((results: PermissionStatus[]) => {
|
||||
if (results.every((result) => result.state === "granted")) {
|
||||
sensor.start();
|
||||
console.log("started")
|
||||
// …
|
||||
|
||||
function checkPerms() {
|
||||
const permissionsToCheck = ['accelerometer', 'gyroscope', 'magnetometer'];
|
||||
const permissionPromises = permissionsToCheck.map(permissionName => {
|
||||
if (!navigator.permissions.query) {
|
||||
console.log('Permissions API not supported');
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
return navigator.permissions.query({ name: permissionName as any })
|
||||
.catch(error => {
|
||||
console.log(`Permission not supported: ${permissionName}`);
|
||||
return null;
|
||||
});
|
||||
}).filter(Boolean);
|
||||
|
||||
Promise.all(permissionPromises).then((results: (PermissionStatus | null)[]) => {
|
||||
const warning = document.getElementById("unsupported-warning") as HTMLElement;
|
||||
const gyro = document.getElementById("gyroBox") as HTMLElement;
|
||||
const accel = document.getElementById("accelBox") as HTMLElement;
|
||||
const orient = document.getElementById("orientBox") as HTMLElement;
|
||||
let isAccelerometerSupported = "Accelerometer" in window;
|
||||
let isGyroscopeSupported = "Gyroscope" in window;
|
||||
let isAbsoluteOrientationSensorSupported = "AbsoluteOrientationSensor" in window;
|
||||
|
||||
if (!results.every((result) => result !== null && result.state === "granted")) {
|
||||
show(warning)
|
||||
console.log("shown")
|
||||
} else {
|
||||
console.log("No permissions to use AbsoluteOrientationSensor.");
|
||||
if (isAccelerometerSupported && false) {
|
||||
console.log("Accelerometer is supported.");
|
||||
show(accel)
|
||||
sensorStart("Accelerometer", accel, "accel");
|
||||
}
|
||||
if (isGyroscopeSupported && false) {
|
||||
console.log("Gyroscope is supported.");
|
||||
show(gyro)
|
||||
sensorStart("Gyroscope", gyro, "gyro");
|
||||
}
|
||||
if (isAccelerometerSupported) {
|
||||
console.log("AbsoluteOrientationSensor is supported.");
|
||||
show(orient)
|
||||
sensorStart("AbsoluteOrientationSensor", orient, "orient");
|
||||
}
|
||||
|
||||
if (!isAccelerometerSupported && !isGyroscopeSupported && !isAbsoluteOrientationSensorSupported) {
|
||||
console.log("None of the interfaces are supported.");
|
||||
show(warning)
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('AbsoluteOrientationSensor is not supported in this browser.');
|
||||
})
|
||||
};
|
||||
|
||||
function setupThreeJsScene() {
|
||||
const sceneSize = new THREE.Vector3(100, 100, 100);
|
||||
const renderer = new THREE.WebGLRenderer({ alpha: true });
|
||||
renderer.setSize(sceneSize.x, sceneSize.y);
|
||||
renderer.setPixelRatio(window.devicePixelRatio / 2.5);
|
||||
const scene = new THREE.Scene();
|
||||
|
||||
const axes = new THREE.AxesHelper(5);
|
||||
scene.add(axes);
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(75, sceneSize.x / sceneSize.y, 0.1, 1000);
|
||||
camera.translateOnAxis(scene.up.clone(), 2);
|
||||
camera.lookAt(axes.position);
|
||||
|
||||
return { renderer, scene, axes, camera };
|
||||
}
|
||||
|
||||
// Create a renderer
|
||||
const sceneWidth = 100;
|
||||
const sceneHeight = 100;
|
||||
const downscaling = 1; // 1 is no downscaling and higher is more downscaling
|
||||
const renderer = new THREE.WebGLRenderer({ alpha: true });
|
||||
renderer.setSize(sceneWidth, sceneHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio / downscaling);
|
||||
(document.getElementById("gyroBox") || document.body).appendChild(renderer.domElement);
|
||||
|
||||
|
||||
// Create a scene
|
||||
const scene = new THREE.Scene();
|
||||
|
||||
// Create a camera
|
||||
const camera = new THREE.PerspectiveCamera(50, sceneWidth / sceneHeight, 0.1, 1000);
|
||||
// Move the camera backwards
|
||||
camera.position.y = 2;
|
||||
// Point the camera towards the origin
|
||||
camera.lookAt(new THREE.Vector3(0, 0, 0));
|
||||
|
||||
|
||||
// Define a vector representing the initial state (e.g., pointing up)
|
||||
let xVec = new THREE.Vector3(1, 0, 0); // x-arrow pointing in positive x-direction
|
||||
let yVec = new THREE.Vector3(0, 1, 0); // y-arrow pointing in positive y-direction
|
||||
let zVec = new THREE.Vector3(0, 0, 1); // z-arrow pointing in positive z-direction
|
||||
|
||||
|
||||
// Create an arrow
|
||||
const origin = new THREE.Vector3(0, 0, 0);
|
||||
const length = 1;
|
||||
const xColor = 0xff0000;
|
||||
const yColor = 0x00ff00;
|
||||
const zColor = 0x0000ff;
|
||||
const xArrow = new THREE.ArrowHelper(xVec, origin, length, xColor);
|
||||
const yArrow = new THREE.ArrowHelper(yVec, origin, length, yColor);
|
||||
const zArrow = new THREE.ArrowHelper(zVec, origin, length, zColor);
|
||||
let orientation = new THREE.Quaternion();
|
||||
|
||||
// Add the arrow to the scene
|
||||
scene.add(xArrow, yArrow, zArrow);
|
||||
|
||||
// Profiling
|
||||
let frameTime = 0; // Time last frame was taken
|
||||
let frameCount = 0; // Number of frames since the last second
|
||||
let frameSec = 0; // Time last second was recorded for a frame
|
||||
|
||||
let sampleTime = 0; // Time last frame was taken
|
||||
let sampleCount = 0; // Number of frames since the last second
|
||||
let sampleSec = 0; // Time last second was recorded for a frame
|
||||
|
||||
// Animation loop
|
||||
let setFPS = 60; // Desired framerate
|
||||
let fps = 0; // Startup fps
|
||||
let clock = new THREE.Clock();
|
||||
let delta = 0;
|
||||
|
||||
function animate() {
|
||||
requestAnimationFrame(animate);
|
||||
delta += clock.getDelta();
|
||||
|
||||
if (delta > 1 / fps) {
|
||||
|
||||
// Orient and render the cursor
|
||||
orientCursor();
|
||||
render();
|
||||
|
||||
// Profiling
|
||||
let currTime = Date.now();
|
||||
if (currTime - frameTime >= 1000) {
|
||||
console.log("Frames: " + frameCount)
|
||||
frameCount = 0;
|
||||
frameTime = currTime;
|
||||
}
|
||||
else { frameCount++; }
|
||||
delta %= 1 / fps;
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
// Render the scene with the camera
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
// Initialize default orientation
|
||||
let initialOrientation: THREE.Quaternion | null = null;
|
||||
let relOrientation: THREE.Quaternion | null = null;
|
||||
|
||||
function orientCursor() {
|
||||
if (initialOrientation !== null) {
|
||||
relOrientation = new THREE.Quaternion().multiplyQuaternions(orientation, initialOrientation?.clone().invert());
|
||||
}
|
||||
else {
|
||||
relOrientation = orientation;
|
||||
console.log("fallback orientation")
|
||||
}
|
||||
// Create a vector for each arrow's initial orientation
|
||||
let xInit = new THREE.Vector3(1, 0, 0); // x-arrow pointing in positive x-direction
|
||||
let yInit = new THREE.Vector3(0, 1, 0); // y-arrow pointing in positive y-direction
|
||||
let zInit = new THREE.Vector3(0, 0, 1); // z-arrow pointing in positive z-direction
|
||||
|
||||
// Apply the orientation quaternion to the initial vectors
|
||||
let xOrient = xInit.clone().applyQuaternion(relOrientation);
|
||||
let yOrient = yInit.clone().applyQuaternion(relOrientation);
|
||||
let zOrient = zInit.clone().applyQuaternion(relOrientation);
|
||||
|
||||
// Set the direction of the arrows
|
||||
xArrow.setDirection(xOrient);
|
||||
yArrow.setDirection(yOrient);
|
||||
zArrow.setDirection(zOrient);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function calibrate() {
|
||||
if (initialOrientation == null) {
|
||||
console.log("Oriented");
|
||||
initialOrientation = orientation;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if AbsoluteOrientationSensor is defined
|
||||
if (window.AbsoluteOrientationSensor) {
|
||||
// Create an AbsoluteOrientationSensor object
|
||||
const sensor = new window.AbsoluteOrientationSensor({ frequency: 60, referenceFrame: 'device' });
|
||||
|
||||
|
||||
// Add an event listener for sensor readings
|
||||
function handleSensorReading(
|
||||
sensor: any,
|
||||
scene: THREE.Scene,
|
||||
calibratedRotation: THREE.Quaternion | null,
|
||||
render: (direction: THREE.Quaternion | null) => void,
|
||||
checkbox: HTMLInputElement | null
|
||||
) {
|
||||
let fps = 0;
|
||||
const setFPS = 60;
|
||||
sensor.addEventListener('reading', () => {
|
||||
// Apply the sensor's quaternion to the vector
|
||||
orientation = new THREE.Quaternion(...sensor.quaternion);
|
||||
// Normalize the quaternion
|
||||
orientation.normalize;
|
||||
const orientation = new THREE.Quaternion(...sensor.quaternion).normalize();
|
||||
// Set the initial orientation if it's not set already
|
||||
calibrate();
|
||||
// Profiling
|
||||
let currTime = new Date().getTime()
|
||||
if (sampleSec < currTime - 1000) {
|
||||
console.log("Samples: " + sampleCount)
|
||||
sampleCount = 0;
|
||||
sampleSec = currTime;
|
||||
if (!calibratedRotation) {
|
||||
calibratedRotation = orientation.invert();
|
||||
}
|
||||
else { sampleCount++; }
|
||||
sampleTime = currTime;
|
||||
const relativeOrientation = orientation.clone().multiply(calibratedRotation.clone());
|
||||
render(relativeOrientation);
|
||||
});
|
||||
|
||||
// Get the button element
|
||||
const checkbox = document.getElementById('gyro') as HTMLInputElement;
|
||||
console.log("checkboxgotted: " + checkbox)
|
||||
|
||||
// Check if the button was found
|
||||
if (checkbox) {
|
||||
// Add a click event listener to the button
|
||||
|
@ -262,15 +176,13 @@ if (window.AbsoluteOrientationSensor) {
|
|||
if (!this.checked) {
|
||||
sensor.stop();
|
||||
console.log("stopped");
|
||||
orientation = new THREE.Quaternion();
|
||||
fps = 0;
|
||||
initialOrientation = null;
|
||||
orientCursor();
|
||||
render();
|
||||
render(null);
|
||||
} else {
|
||||
// Otherwise, start the sensor
|
||||
sensor.start();
|
||||
console.log("started");
|
||||
calibratedRotation = null;
|
||||
fps = setFPS;
|
||||
}
|
||||
});
|
||||
|
@ -278,11 +190,48 @@ if (window.AbsoluteOrientationSensor) {
|
|||
else {
|
||||
console.log(checkbox)
|
||||
}
|
||||
|
||||
// Start the animation loop
|
||||
animate();
|
||||
render();
|
||||
} else {
|
||||
// Log a message to the console if AbsoluteOrientationSensor is not supported
|
||||
console.log('AbsoluteOrientationSensor is not supported in this browser.');
|
||||
}
|
||||
|
||||
type sensorType = "Accelerometer" | "Gyroscope" | "AbsoluteOrientationSensor";
|
||||
function sensorStart(sensorName: sensorType, box: HTMLElement, checkboxId: string) {
|
||||
const sensorConstructors: { [K in sensorType]: any } = {
|
||||
"Accelerometer": window.Accelerometer,
|
||||
"Gyroscope": window.Gyroscope,
|
||||
"AbsoluteOrientationSensor": window.AbsoluteOrientationSensor
|
||||
};
|
||||
const SensorConstructor = sensorConstructors[sensorName];
|
||||
if (SensorConstructor) {
|
||||
const sensor = new SensorConstructor({ frequency: 60, referenceFrame: 'device' });
|
||||
|
||||
// Set up Three.js scene
|
||||
const { renderer, scene, axes, camera } = setupThreeJsScene();
|
||||
box.appendChild(renderer.domElement)
|
||||
|
||||
// Define render function
|
||||
const render = (direction: THREE.Quaternion | null) => {
|
||||
if (!direction) {
|
||||
direction = new THREE.Quaternion().identity();
|
||||
}
|
||||
|
||||
axes.setRotationFromQuaternion(direction);
|
||||
renderer.render(scene, camera);
|
||||
}
|
||||
|
||||
// Initialize default orientation
|
||||
let calibratedRotation: THREE.Quaternion | null = null;
|
||||
let currentDirection: THREE.Vector3 | null = null;
|
||||
let relativeDirection: THREE.Vector3 | null = null;
|
||||
|
||||
var checkbox = document.getElementById(checkboxId) as HTMLInputElement;
|
||||
|
||||
// Handle sensor readings
|
||||
handleSensorReading(sensor, scene, calibratedRotation, render, checkbox);
|
||||
render(null);
|
||||
|
||||
// Render the first frame
|
||||
} else {
|
||||
console.log(`No constructor found for sensor: ${sensorName}`);
|
||||
}
|
||||
}
|
||||
|
||||
checkPerms();
|
|
@ -60,11 +60,33 @@
|
|||
<input type="range" id="fr_size" name="freq_range" min="0" max="127">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h1>Controls</h1>
|
||||
<div class="flex-container">
|
||||
<div class="button-box">
|
||||
<div hidden class="combo-switch" id="gyroBox">
|
||||
<input type="checkbox" id="gyro" name="tilt">
|
||||
<h3>Tilt</h3>
|
||||
<div id="debugGyro"></div>
|
||||
</div>
|
||||
|
||||
<div hidden class="combo-switch" id="accelBox">
|
||||
<input type="checkbox" id="accel" name="swing">
|
||||
<h3>Swing</h3>
|
||||
<div id="debugAccel"></div>
|
||||
</div>
|
||||
|
||||
<div hidden class="combo-switch" id="orientBox">
|
||||
<input type="checkbox" id="orient" name="move">
|
||||
<h3>Move</h3>
|
||||
<div id="debugOrient"></div>
|
||||
</div>
|
||||
|
||||
<div class="combo-switch" id="gyroBox">
|
||||
<input type="checkbox" id="gyro" name="gyro">
|
||||
<h3>Gyro</h3>
|
||||
</div>
|
||||
<p hidden class="warning" id="unsupported-warning">
|
||||
Uh Oh! Seems like your device doesn't support any control options :(
|
||||
You can still use the sliders above though !
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
|
Loading…
Reference in New Issue