diff --git a/sim/state/accelerometer.ts b/sim/state/accelerometer.ts index 18d3d588..0aca8166 100644 --- a/sim/state/accelerometer.ts +++ b/sim/state/accelerometer.ts @@ -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); } } } \ No newline at end of file diff --git a/sim/visuals/boardview.ts b/sim/visuals/boardview.ts index 9096285c..878dcbff 100644 --- a/sim/visuals/boardview.ts +++ b/sim/visuals/boardview.ts @@ -3,7 +3,6 @@ namespace pxsim.visuals { return new visuals.MicrobitBoardSvg({ runtime: runtime, theme: visuals.randomTheme(opts.highContrast), - disableTilt: false, wireframe: opts.wireframe }); } diff --git a/sim/visuals/microbit.ts b/sim/visuals/microbit.ts index 7fabad54..f33a690f 100644 --- a/sim/visuals/microbit.ts +++ b/sim/visuals/microbit.ts @@ -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 = {}; @@ -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" });