From 910772d54ebead95a561f3948bda6600a0c88c0a Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 9 Sep 2016 22:56:26 -0700 Subject: [PATCH] refacotring various simulator features into pxt --- sim/dalboard.ts | 8 +- sim/microbit.ts | 19 ---- sim/state/buttonpair.ts | 28 +----- sim/state/compass.ts | 7 -- sim/state/ledmatrix.ts | 66 ------------ sim/state/lightsensor.ts | 7 -- sim/state/misc.ts | 52 ---------- sim/visuals/buttonpair.ts | 204 -------------------------------------- 8 files changed, 11 insertions(+), 380 deletions(-) delete mode 100644 sim/visuals/buttonpair.ts diff --git a/sim/dalboard.ts b/sim/dalboard.ts index adeb064b..2ccf966a 100644 --- a/sim/dalboard.ts +++ b/sim/dalboard.ts @@ -29,7 +29,13 @@ namespace pxsim { // components this.ledMatrixState = new LedMatrixState(runtime); - this.buttonPairState = new ButtonPairState(); + this.buttonPairState = new ButtonPairState({ + ID_BUTTON_A: DAL.MICROBIT_ID_BUTTON_A, + ID_BUTTON_B: DAL.MICROBIT_ID_BUTTON_B, + ID_BUTTON_AB: DAL.MICROBIT_ID_BUTTON_AB, + BUTTON_EVT_UP: DAL.MICROBIT_BUTTON_EVT_UP, + BUTTON_EVT_CLICK: DAL.MICROBIT_BUTTON_EVT_CLICK + }); this.edgeConnectorState = new EdgeConnectorState(); this.radioState = new RadioState(runtime); this.accelerometerState = new AccelerometerState(runtime); diff --git a/sim/microbit.ts b/sim/microbit.ts index 3d366c2c..95f4238e 100644 --- a/sim/microbit.ts +++ b/sim/microbit.ts @@ -226,25 +226,6 @@ namespace pxsim.visuals { wireframe?: boolean; } - export interface IPointerEvents { - up: string, - down: string, - move: string, - leave: string - } - - export const pointerEvents = !!(window as any).PointerEvent ? { - up: "pointerup", - down: "pointerdown", - move: "pointermove", - leave: "pointerleave" - } : { - up: "mouseup", - down: "mousedown", - move: "mousemove", - leave: "mouseleave" - }; - export class MicrobitBoardSvg implements BoardView { public element: SVGSVGElement; private style: SVGStyleElement; diff --git a/sim/state/buttonpair.ts b/sim/state/buttonpair.ts index 31778c6d..419b8d39 100644 --- a/sim/state/buttonpair.ts +++ b/sim/state/buttonpair.ts @@ -1,7 +1,7 @@ namespace pxsim.input { export function onButtonPressed(button: number, handler: RefAction): void { let b = board().buttonPairState; - if (button == DAL.MICROBIT_ID_BUTTON_AB && !b.usesButtonAB) { + if (button == b.props.ID_BUTTON_AB && !b.usesButtonAB) { b.usesButtonAB = true; runtime.queueDisplayUpdate(); } @@ -10,32 +10,12 @@ namespace pxsim.input { export function buttonIsPressed(button: number): boolean { let b = board().buttonPairState; - if (button == DAL.MICROBIT_ID_BUTTON_AB && !b.usesButtonAB) { + if (button == b.abBtn.id && !b.usesButtonAB) { b.usesButtonAB = true; runtime.queueDisplayUpdate(); } - if (button == DAL.MICROBIT_ID_BUTTON_A) return b.aBtn.pressed; - if (button == DAL.MICROBIT_ID_BUTTON_B) return b.bBtn.pressed; + if (button == b.aBtn.id) return b.aBtn.pressed; + if (button == b.bBtn.id) return b.bBtn.pressed; return b.abBtn.pressed || (b.aBtn.pressed && b.bBtn.pressed); } } - -namespace pxsim { - export class Button { - constructor(public id: number) { } - pressed: boolean; - } - - export class ButtonPairState { - usesButtonAB: boolean = false; - aBtn: Button; - bBtn: Button; - abBtn: Button; - - constructor() { - this.aBtn = new Button(DAL.MICROBIT_ID_BUTTON_A); - this.bBtn = new Button(DAL.MICROBIT_ID_BUTTON_B); - this.abBtn = new Button(DAL.MICROBIT_ID_BUTTON_AB); - } - } -} \ No newline at end of file diff --git a/sim/state/compass.ts b/sim/state/compass.ts index 36f3614f..debf76f4 100644 --- a/sim/state/compass.ts +++ b/sim/state/compass.ts @@ -12,11 +12,4 @@ namespace pxsim.input { // TODO return 0; } -} - -namespace pxsim { - export class CompassState { - usesHeading = false; - heading = 90; - } } \ No newline at end of file diff --git a/sim/state/ledmatrix.ts b/sim/state/ledmatrix.ts index 332345c2..91909b0b 100644 --- a/sim/state/ledmatrix.ts +++ b/sim/state/ledmatrix.ts @@ -116,72 +116,6 @@ namespace pxsim { } return font; } - - export interface AnimationOptions { - interval: number; - // false means last frame - frame: () => boolean; - whenDone?: (cancelled: boolean) => void; - } - - export class AnimationQueue { - private queue: AnimationOptions[] = []; - private process: () => void; - - constructor(private runtime: Runtime) { - this.process = () => { - let top = this.queue[0] - if (!top) return - if (this.runtime.dead) return - runtime = this.runtime - let res = top.frame() - runtime.queueDisplayUpdate() - runtime.maybeUpdateDisplay() - if (res === false) { - this.queue.shift(); - // if there is already something in the queue, start processing - if (this.queue[0]) - setTimeout(this.process, this.queue[0].interval) - // this may push additional stuff - top.whenDone(false); - } else { - setTimeout(this.process, top.interval) - } - } - } - - public cancelAll() { - let q = this.queue - this.queue = [] - for (let a of q) { - a.whenDone(true) - } - } - - public cancelCurrent() { - let top = this.queue[0] - if (top) { - this.queue.shift(); - top.whenDone(true); - } - } - - public enqueue(anim: AnimationOptions) { - if (!anim.whenDone) anim.whenDone = () => { }; - this.queue.push(anim) - // we start processing when the queue goes from 0 to 1 - if (this.queue.length == 1) - this.process() - } - - public executeAsync(anim: AnimationOptions) { - U.assert(!anim.whenDone) - return new Promise((resolve, reject) => { - anim.whenDone = resolve - this.enqueue(anim) - }) - } - } } namespace pxsim.images { diff --git a/sim/state/lightsensor.ts b/sim/state/lightsensor.ts index 5df56147..0aa78751 100644 --- a/sim/state/lightsensor.ts +++ b/sim/state/lightsensor.ts @@ -1,10 +1,3 @@ -namespace pxsim { - export class LightSensorState { - usesLightLevel = false; - lightLevel = 128; - } -} - namespace pxsim.input { export function lightLevel(): number { let b = board().lightSensorState; diff --git a/sim/state/misc.ts b/sim/state/misc.ts index db0f622c..cbce22f8 100644 --- a/sim/state/misc.ts +++ b/sim/state/misc.ts @@ -22,58 +22,6 @@ namespace pxsim { throw new Error("PANIC " + code) } - export namespace AudioContextManager { - let _context: any; // AudioContext - let _vco: any; // OscillatorNode; - let _vca: any; // GainNode; - - function context(): any { - if (!_context) _context = freshContext(); - return _context; - } - - function freshContext(): any { - (window).AudioContext = (window).AudioContext || (window).webkitAudioContext; - if ((window).AudioContext) { - try { - // this call my crash. - // SyntaxError: audio resources unavailable for AudioContext construction - return new (window).AudioContext(); - } catch (e) { } - } - return undefined; - } - - export function stop() { - if (_vca) _vca.gain.value = 0; - } - - export function tone(frequency: number, gain: number) { - if (frequency <= 0) return; - let ctx = context(); - if (!ctx) return; - - gain = Math.max(0, Math.min(1, gain)); - if (!_vco) { - try { - _vco = ctx.createOscillator(); - _vca = ctx.createGain(); - _vco.connect(_vca); - _vca.connect(ctx.destination); - _vca.gain.value = gain; - _vco.start(0); - } catch (e) { - _vco = undefined; - _vca = undefined; - return; - } - } - - _vco.frequency.value = frequency; - _vca.gain.value = gain; - } - } - export interface RuntimeOptions { theme: string; } diff --git a/sim/visuals/buttonpair.ts b/sim/visuals/buttonpair.ts deleted file mode 100644 index 2e326d52..00000000 --- a/sim/visuals/buttonpair.ts +++ /dev/null @@ -1,204 +0,0 @@ -/// -/// -/// - -namespace pxsim.visuals { - export function mkBtnSvg(xy: Coord): SVGAndSize { - let [innerCls, outerCls] = ["sim-button", "sim-button-outer"]; - const tabSize = PIN_DIST / 2.5; - const pegR = PIN_DIST / 5; - const btnR = PIN_DIST * .8; - const pegMargin = PIN_DIST / 8; - const plateR = PIN_DIST / 12; - - const pegOffset = pegMargin + pegR; - let [x, y] = xy; - const left = x - tabSize / 2; - const top = y - tabSize / 2; - const plateH = 3 * PIN_DIST - tabSize; - const plateW = 2 * PIN_DIST + tabSize; - const plateL = left; - const plateT = top + tabSize; - const btnCX = plateL + plateW / 2; - const btnCY = plateT + plateH / 2; - - let btng = svg.elt("g"); - //tabs - const mkTab = (x: number, y: number) => { - svg.child(btng, "rect", { class: "sim-button-tab", x: x, y: y, width: tabSize, height: tabSize}) - } - mkTab(left, top); - mkTab(left + 2 * PIN_DIST, top); - mkTab(left, top + 3 * PIN_DIST); - mkTab(left + 2 * PIN_DIST, top + 3 * PIN_DIST); - - //plate - svg.child(btng, "rect", { class: outerCls, x: plateL, y: plateT, rx: plateR, ry: plateR, width: plateW, height: plateH }); - - //pegs - const mkPeg = (x: number, y: number) => { - svg.child(btng, "circle", { class: "sim-button-nut", cx: x, cy: y, r: pegR }); - } - mkPeg(plateL + pegOffset, plateT + pegOffset) - mkPeg(plateL + plateW - pegOffset, plateT + pegOffset) - mkPeg(plateL + pegOffset, plateT + plateH - pegOffset) - mkPeg(plateL + plateW - pegOffset, plateT + plateH - pegOffset) - - //inner btn - let innerBtn = svg.child(btng, "circle", { class: innerCls, cx: btnCX, cy: btnCY, r: btnR }); - - //return - return { el: btng, y: top, x: left, w: plateW, h: plateH + 2 * tabSize }; - } - export const BUTTON_PAIR_STYLE = ` - .sim-button { - pointer-events: none; - fill: #000; - } - .sim-button-outer:active ~ .sim-button, - .sim-button-virtual:active { - fill: #FFA500; - } - .sim-button-outer { - cursor: pointer; - fill: #979797; - } - .sim-button-outer:hover { - stroke:gray; - stroke-width: ${PIN_DIST / 5}px; - } - .sim-button-nut { - fill:#000; - pointer-events:none; - } - .sim-button-nut:hover { - stroke:${PIN_DIST / 15}px solid #704A4A; - } - .sim-button-tab { - fill:#FFF; - pointer-events:none; - } - .sim-button-virtual { - cursor: pointer; - fill: rgba(255, 255, 255, 0.6); - stroke: rgba(255, 255, 255, 1); - stroke-width: ${PIN_DIST / 5}px; - } - .sim-button-virtual:hover { - stroke: rgba(128, 128, 128, 1); - } - .sim-text-virtual { - fill: #000; - pointer-events:none; - } - `; - export class ButtonPairView implements IBoardPart { - public element: SVGElement; - public defs: SVGElement[]; - public style = BUTTON_PAIR_STYLE; - private state: ButtonPairState; - private bus: EventBus; - private aBtn: SVGGElement; - private bBtn: SVGGElement; - private abBtn: SVGGElement; - - public init(bus: EventBus, state: ButtonPairState) { - this.state = state; - this.bus = bus; - this.defs = []; - this.element = this.mkBtns(); - this.updateState(); - this.attachEvents(); - } - - public moveToCoord(xy: Coord) { - let btnWidth = PIN_DIST * 3; - let [x, y] = xy; - translateEl(this.aBtn, [x, y]) - translateEl(this.bBtn, [x + btnWidth, y]) - translateEl(this.abBtn, [x + PIN_DIST * 1.5, y + PIN_DIST * 4]) - } - - public updateState() { - let stateBtns = [this.state.aBtn, this.state.bBtn, this.state.abBtn]; - let svgBtns = [this.aBtn, this.bBtn, this.abBtn]; - - if (this.state.usesButtonAB && this.abBtn.style.visibility != "visible") { - this.abBtn.style.visibility = "visible"; - } - } - - public updateTheme() {} - - private mkBtns() { - this.aBtn = mkBtnSvg([0, 0]).el; - this.bBtn = mkBtnSvg([0, 0]).el; - - const mkVirtualBtn = () => { - const numPins = 2; - const w = PIN_DIST * 2.8; - const offset = (w - (numPins * PIN_DIST)) / 2; - const corner = PIN_DIST / 2; - const cx = 0 - offset + w / 2; - const cy = cx; - const txtSize = PIN_DIST * 1.3; - const x = -offset; - const y = -offset; - const txtXOff = PIN_DIST / 7; - const txtYOff = PIN_DIST / 10; - - let btng = svg.elt("g"); - let btn = svg.child(btng, "rect", { class: "sim-button-virtual", x: x, y: y, rx: corner, ry: corner, width: w, height: w}); - let btnTxt = mkTxt(cx + txtXOff, cy + txtYOff, txtSize, 0, "A+B"); - svg.addClass(btnTxt, "sim-text") - svg.addClass(btnTxt, "sim-text-virtual"); - btng.appendChild(btnTxt); - - return btng; - } - - this.abBtn = mkVirtualBtn(); - this.abBtn.style.visibility = "hidden"; - - let el = svg.elt("g"); - svg.addClass(el, "sim-buttonpair") - el.appendChild(this.aBtn); - el.appendChild(this.bBtn); - el.appendChild(this.abBtn); - - return el; - } - - private attachEvents() { - let btnStates = [this.state.aBtn, this.state.bBtn]; - let btnSvgs = [this.aBtn, this.bBtn]; - btnSvgs.forEach((btn, index) => { - btn.addEventListener(pointerEvents.down, ev => { - btnStates[index].pressed = true; - }) - btn.addEventListener(pointerEvents.leave, ev => { - btnStates[index].pressed = false; - }) - btn.addEventListener(pointerEvents.up, ev => { - btnStates[index].pressed = false; - this.bus.queue(btnStates[index].id, DAL.MICROBIT_BUTTON_EVT_UP); - this.bus.queue(btnStates[index].id, DAL.MICROBIT_BUTTON_EVT_CLICK); - }) - }) - let updateBtns = (s: boolean) => { - btnStates.forEach(b => b.pressed = s) - }; - this.abBtn.addEventListener(pointerEvents.down, ev => { - updateBtns(true); - }) - this.abBtn.addEventListener(pointerEvents.leave, ev => { - updateBtns(false); - }) - this.abBtn.addEventListener(pointerEvents.up, ev => { - updateBtns(false); - this.bus.queue(this.state.abBtn.id, DAL.MICROBIT_BUTTON_EVT_UP); - this.bus.queue(this.state.abBtn.id, DAL.MICROBIT_BUTTON_EVT_CLICK); - }) - } - } -} \ No newline at end of file