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:
		@@ -13,12 +13,19 @@ namespace pxsim.input {
 | 
				
			|||||||
    export function acceleration(dimension: number): number {
 | 
					    export function acceleration(dimension: number): number {
 | 
				
			||||||
        let b = board().accelerometerState;
 | 
					        let b = board().accelerometerState;
 | 
				
			||||||
        let acc = b.accelerometer;
 | 
					        let acc = b.accelerometer;
 | 
				
			||||||
        acc.activate();
 | 
					 | 
				
			||||||
        switch (dimension) {
 | 
					        switch (dimension) {
 | 
				
			||||||
            case 0: return acc.getX();
 | 
					            case 0: 
 | 
				
			||||||
            case 1: return acc.getY();
 | 
					                acc.activate(AccelerometerFlag.X);
 | 
				
			||||||
            case 2: return acc.getZ();
 | 
					                return acc.getX();
 | 
				
			||||||
            default: return Math.floor(Math.sqrt(acc.instantaneousAccelerationSquared()));
 | 
					            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
 | 
					        NORTH_EAST_DOWN
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    export enum AccelerometerFlag {
 | 
				
			||||||
 | 
					        X = 1,
 | 
				
			||||||
 | 
					        Y = 2,
 | 
				
			||||||
 | 
					        Z = 4
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    export class Accelerometer {
 | 
					    export class Accelerometer {
 | 
				
			||||||
        private sigma: number = 0;              // the number of ticks that the instantaneous gesture has been stable.
 | 
					        private sigma: number = 0;              // the number of ticks that the instantaneous gesture has been stable.
 | 
				
			||||||
        private lastGesture: number = 0;       // the last, stable gesture recorded.
 | 
					        private lastGesture: number = 0;       // the last, stable gesture recorded.
 | 
				
			||||||
@@ -110,6 +123,7 @@ namespace pxsim {
 | 
				
			|||||||
        private id: number;
 | 
					        private id: number;
 | 
				
			||||||
        public isActive = false;
 | 
					        public isActive = false;
 | 
				
			||||||
        public sampleRange = 2;
 | 
					        public sampleRange = 2;
 | 
				
			||||||
 | 
					        public flags: AccelerometerFlag = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        constructor(public runtime: Runtime) {
 | 
					        constructor(public runtime: Runtime) {
 | 
				
			||||||
            this.id = DAL.MICROBIT_ID_ACCELEROMETER;
 | 
					            this.id = DAL.MICROBIT_ID_ACCELEROMETER;
 | 
				
			||||||
@@ -120,11 +134,13 @@ namespace pxsim {
 | 
				
			|||||||
            this.sampleRange = Math.max(1, Math.min(8, range));
 | 
					            this.sampleRange = Math.max(1, Math.min(8, range));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public activate() {
 | 
					        public activate(flags?: AccelerometerFlag) {
 | 
				
			||||||
            if (!this.isActive) {
 | 
					            if (!this.isActive) {
 | 
				
			||||||
                this.isActive = true;
 | 
					                this.isActive = true;
 | 
				
			||||||
                this.runtime.queueDisplayUpdate();
 | 
					                this.runtime.queueDisplayUpdate();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            if (flags)
 | 
				
			||||||
 | 
					                this.flags |= flags;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,6 @@ namespace pxsim.visuals {
 | 
				
			|||||||
        return new visuals.MicrobitBoardSvg({
 | 
					        return new visuals.MicrobitBoardSvg({
 | 
				
			||||||
            runtime: runtime,
 | 
					            runtime: runtime,
 | 
				
			||||||
            theme: visuals.randomTheme(opts.highContrast),
 | 
					            theme: visuals.randomTheme(opts.highContrast),
 | 
				
			||||||
            disableTilt: false,
 | 
					 | 
				
			||||||
            wireframe: opts.wireframe
 | 
					            wireframe: opts.wireframe
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -274,7 +274,6 @@ path.sim-board {
 | 
				
			|||||||
    export interface IBoardProps {
 | 
					    export interface IBoardProps {
 | 
				
			||||||
        runtime?: pxsim.Runtime;
 | 
					        runtime?: pxsim.Runtime;
 | 
				
			||||||
        theme?: IBoardTheme;
 | 
					        theme?: IBoardTheme;
 | 
				
			||||||
        disableTilt?: boolean;
 | 
					 | 
				
			||||||
        wireframe?: boolean;
 | 
					        wireframe?: boolean;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -306,6 +305,9 @@ path.sim-board {
 | 
				
			|||||||
        private thermometerText: SVGTextElement;
 | 
					        private thermometerText: SVGTextElement;
 | 
				
			||||||
        private shakeButton: SVGCircleElement;
 | 
					        private shakeButton: SVGCircleElement;
 | 
				
			||||||
        private shakeText: SVGTextElement;
 | 
					        private shakeText: SVGTextElement;
 | 
				
			||||||
 | 
					        private accTextX: SVGTextElement;
 | 
				
			||||||
 | 
					        private accTextY: SVGTextElement;
 | 
				
			||||||
 | 
					        private accTextZ: SVGTextElement;
 | 
				
			||||||
        public board: pxsim.DalBoard;
 | 
					        public board: pxsim.DalBoard;
 | 
				
			||||||
        private pinNmToCoord: Map<Coord> = {};
 | 
					        private pinNmToCoord: Map<Coord> = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -694,19 +696,52 @@ path.sim-board {
 | 
				
			|||||||
            accessibility.setLiveContent(lv.toString());
 | 
					            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() {
 | 
					        private updateTilt() {
 | 
				
			||||||
            if (this.props.disableTilt) return;
 | 
					 | 
				
			||||||
            const state = this.board;
 | 
					            const state = this.board;
 | 
				
			||||||
            if (!state || !state.accelerometerState.accelerometer.isActive) return;
 | 
					            if (!state || !state.accelerometerState.accelerometer.isActive) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const x = state.accelerometerState.accelerometer.getX();
 | 
					            const acc = state.accelerometerState.accelerometer;
 | 
				
			||||||
            const y = -state.accelerometerState.accelerometer.getY();
 | 
					            const x = acc.getX();
 | 
				
			||||||
 | 
					            const y = -acc.getY();
 | 
				
			||||||
 | 
					            const z = acc.getZ();
 | 
				
			||||||
            const af = 8 / 1023;
 | 
					            const af = 8 / 1023;
 | 
				
			||||||
            const s = 1 - Math.min(0.1, Math.pow(Math.max(Math.abs(x), Math.abs(y)) / 1023, 2) / 35);
 | 
					            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})`
 | 
					            // fix top parent and apply style to it
 | 
				
			||||||
            this.element.style.perspectiveOrigin = "50% 50% 50%";
 | 
					            const el = this.findParentElement();
 | 
				
			||||||
            this.element.style.perspective = "30em";
 | 
					            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() {
 | 
					        private buildDom() {
 | 
				
			||||||
@@ -729,13 +764,13 @@ path.sim-board {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            // filters
 | 
					            // filters
 | 
				
			||||||
            let ledglow = svg.child(this.defs, "filter", { id: "ledglow", x: "-75%", y: "-75%", width: "300%", height: "300%" });
 | 
					            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, "feMorphology", { operator: "dilate", radius: "4", in: "SourceAlpha", result: "thicken" });
 | 
				
			||||||
            svg.child(ledglow, "feGaussianBlur", { stdDeviation: "5", in: "thicken", result: "blurred"});
 | 
					            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, "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, "feComposite", { in: "glowColor", in2: "blurred", operator: "in", result: "ledglow_colored" });
 | 
				
			||||||
            let ledglowMerge = svg.child(ledglow, "feMerge", {});
 | 
					            let ledglowMerge = svg.child(ledglow, "feMerge", {});
 | 
				
			||||||
            svg.child(ledglowMerge, "feMergeNode", { in: "ledglow_colored"});
 | 
					            svg.child(ledglowMerge, "feMergeNode", { in: "ledglow_colored" });
 | 
				
			||||||
            svg.child(ledglowMerge, "feMergeNode", { in: "SourceGraphic"});
 | 
					            svg.child(ledglowMerge, "feMergeNode", { in: "SourceGraphic" });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let glow = svg.child(this.defs, "filter", { id: "filterglow", x: "-5%", y: "-5%", width: "120%", height: "120%" });
 | 
					            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" });
 | 
					            svg.child(glow, "feGaussianBlur", { stdDeviation: "5", result: "glow" });
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user