Tilt support in breadboard + display of accelerometer values (#1379)
* remove disable tilt option * allow tilting when breadboard is up (music speakers) * display acceleration * only showing acc values if read
This commit is contained in:
parent
50f29d278a
commit
37404acbcc
@ -13,12 +13,19 @@ namespace pxsim.input {
|
||||
export function acceleration(dimension: number): number {
|
||||
let b = board().accelerometerState;
|
||||
let acc = b.accelerometer;
|
||||
acc.activate();
|
||||
switch (dimension) {
|
||||
case 0: return acc.getX();
|
||||
case 1: return acc.getY();
|
||||
case 2: return acc.getZ();
|
||||
default: return Math.floor(Math.sqrt(acc.instantaneousAccelerationSquared()));
|
||||
case 0:
|
||||
acc.activate(AccelerometerFlag.X);
|
||||
return acc.getX();
|
||||
case 1:
|
||||
acc.activate(AccelerometerFlag.Y);
|
||||
return acc.getY();
|
||||
case 2:
|
||||
acc.activate(AccelerometerFlag.Z);
|
||||
return acc.getZ();
|
||||
default:
|
||||
acc.activate();
|
||||
return Math.floor(Math.sqrt(acc.instantaneousAccelerationSquared()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,6 +106,12 @@ namespace pxsim {
|
||||
NORTH_EAST_DOWN
|
||||
}
|
||||
|
||||
export enum AccelerometerFlag {
|
||||
X = 1,
|
||||
Y = 2,
|
||||
Z = 4
|
||||
}
|
||||
|
||||
export class Accelerometer {
|
||||
private sigma: number = 0; // the number of ticks that the instantaneous gesture has been stable.
|
||||
private lastGesture: number = 0; // the last, stable gesture recorded.
|
||||
@ -110,6 +123,7 @@ namespace pxsim {
|
||||
private id: number;
|
||||
public isActive = false;
|
||||
public sampleRange = 2;
|
||||
public flags: AccelerometerFlag = 0;
|
||||
|
||||
constructor(public runtime: Runtime) {
|
||||
this.id = DAL.MICROBIT_ID_ACCELEROMETER;
|
||||
@ -120,11 +134,13 @@ namespace pxsim {
|
||||
this.sampleRange = Math.max(1, Math.min(8, range));
|
||||
}
|
||||
|
||||
public activate() {
|
||||
public activate(flags?: AccelerometerFlag) {
|
||||
if (!this.isActive) {
|
||||
this.isActive = true;
|
||||
this.runtime.queueDisplayUpdate();
|
||||
}
|
||||
if (flags)
|
||||
this.flags |= flags;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -383,7 +399,7 @@ namespace pxsim {
|
||||
useShake = false;
|
||||
|
||||
constructor(runtime: Runtime) {
|
||||
this.accelerometer = new Accelerometer(runtime);
|
||||
this.accelerometer = new Accelerometer(runtime);
|
||||
}
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ namespace pxsim.visuals {
|
||||
return new visuals.MicrobitBoardSvg({
|
||||
runtime: runtime,
|
||||
theme: visuals.randomTheme(opts.highContrast),
|
||||
disableTilt: false,
|
||||
wireframe: opts.wireframe
|
||||
});
|
||||
}
|
||||
|
@ -274,7 +274,6 @@ path.sim-board {
|
||||
export interface IBoardProps {
|
||||
runtime?: pxsim.Runtime;
|
||||
theme?: IBoardTheme;
|
||||
disableTilt?: boolean;
|
||||
wireframe?: boolean;
|
||||
}
|
||||
|
||||
@ -306,6 +305,9 @@ path.sim-board {
|
||||
private thermometerText: SVGTextElement;
|
||||
private shakeButton: SVGCircleElement;
|
||||
private shakeText: SVGTextElement;
|
||||
private accTextX: SVGTextElement;
|
||||
private accTextY: SVGTextElement;
|
||||
private accTextZ: SVGTextElement;
|
||||
public board: pxsim.DalBoard;
|
||||
private pinNmToCoord: Map<Coord> = {};
|
||||
|
||||
@ -694,19 +696,52 @@ path.sim-board {
|
||||
accessibility.setLiveContent(lv.toString());
|
||||
}
|
||||
|
||||
findParentElement() {
|
||||
let el = this.element;
|
||||
while (el.parentNode && el.parentNode.nodeName == "svg")
|
||||
el = el.parentNode as SVGSVGElement;
|
||||
return el;
|
||||
}
|
||||
|
||||
private updateTilt() {
|
||||
if (this.props.disableTilt) return;
|
||||
const state = this.board;
|
||||
if (!state || !state.accelerometerState.accelerometer.isActive) return;
|
||||
|
||||
const x = state.accelerometerState.accelerometer.getX();
|
||||
const y = -state.accelerometerState.accelerometer.getY();
|
||||
const acc = state.accelerometerState.accelerometer;
|
||||
const x = acc.getX();
|
||||
const y = -acc.getY();
|
||||
const z = acc.getZ();
|
||||
const af = 8 / 1023;
|
||||
const s = 1 - Math.min(0.1, Math.pow(Math.max(Math.abs(x), Math.abs(y)) / 1023, 2) / 35);
|
||||
|
||||
this.element.style.transform = `perspective(30em) rotateX(${y * af}deg) rotateY(${x * af}deg) scale(${s}, ${s})`
|
||||
this.element.style.perspectiveOrigin = "50% 50% 50%";
|
||||
this.element.style.perspective = "30em";
|
||||
// fix top parent and apply style to it
|
||||
const el = this.findParentElement();
|
||||
el.style.transform = `perspective(30em) rotateX(${y * af}deg) rotateY(${x * af}deg) scale(${s}, ${s})`
|
||||
el.style.perspectiveOrigin = "50% 50% 50%";
|
||||
el.style.perspective = "30em";
|
||||
|
||||
// update text
|
||||
if (acc.flags & AccelerometerFlag.X) {
|
||||
if (!this.accTextX) {
|
||||
this.accTextX = svg.child(this.g, "text", { x: 365, y: 260, class: "sim-text" }) as SVGTextElement;
|
||||
this.accTextX.textContent = "";
|
||||
}
|
||||
this.accTextX.textContent = `ax:${x}`;
|
||||
}
|
||||
if (acc.flags & AccelerometerFlag.Y) {
|
||||
if (!this.accTextY) {
|
||||
this.accTextY = svg.child(this.g, "text", { x: 365, y: 285, class: "sim-text" }) as SVGTextElement;
|
||||
this.accTextY.textContent = "";
|
||||
}
|
||||
this.accTextY.textContent = `ay:${-y}`;
|
||||
}
|
||||
if (acc.flags & AccelerometerFlag.Z) {
|
||||
if (!this.accTextZ) {
|
||||
this.accTextZ = svg.child(this.g, "text", { x: 365, y: 310, class: "sim-text" }) as SVGTextElement;
|
||||
this.accTextZ.textContent = "";
|
||||
}
|
||||
this.accTextZ.textContent = `az:${z}`;
|
||||
}
|
||||
}
|
||||
|
||||
private buildDom() {
|
||||
@ -729,13 +764,13 @@ path.sim-board {
|
||||
|
||||
// filters
|
||||
let ledglow = svg.child(this.defs, "filter", { id: "ledglow", x: "-75%", y: "-75%", width: "300%", height: "300%" });
|
||||
svg.child(ledglow, "feMorphology", { operator: "dilate", radius: "4", in: "SourceAlpha", result: "thicken"});
|
||||
svg.child(ledglow, "feGaussianBlur", { stdDeviation: "5", in: "thicken", result: "blurred"});
|
||||
svg.child(ledglow, "feFlood", { "flood-color": "rgb(255, 17, 77)", result: "glowColor"});
|
||||
svg.child(ledglow, "feComposite", { in: "glowColor", in2: "blurred", operator: "in", result: "ledglow_colored"});
|
||||
svg.child(ledglow, "feMorphology", { operator: "dilate", radius: "4", in: "SourceAlpha", result: "thicken" });
|
||||
svg.child(ledglow, "feGaussianBlur", { stdDeviation: "5", in: "thicken", result: "blurred" });
|
||||
svg.child(ledglow, "feFlood", { "flood-color": "rgb(255, 17, 77)", result: "glowColor" });
|
||||
svg.child(ledglow, "feComposite", { in: "glowColor", in2: "blurred", operator: "in", result: "ledglow_colored" });
|
||||
let ledglowMerge = svg.child(ledglow, "feMerge", {});
|
||||
svg.child(ledglowMerge, "feMergeNode", { in: "ledglow_colored"});
|
||||
svg.child(ledglowMerge, "feMergeNode", { in: "SourceGraphic"});
|
||||
svg.child(ledglowMerge, "feMergeNode", { in: "ledglow_colored" });
|
||||
svg.child(ledglowMerge, "feMergeNode", { in: "SourceGraphic" });
|
||||
|
||||
let glow = svg.child(this.defs, "filter", { id: "filterglow", x: "-5%", y: "-5%", width: "120%", height: "120%" });
|
||||
svg.child(glow, "feGaussianBlur", { stdDeviation: "5", result: "glow" });
|
||||
|
Loading…
Reference in New Issue
Block a user