From 5edd06c9b95f691376f011fe7805437db920c929 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Mon, 26 Sep 2016 13:26:43 -0700 Subject: [PATCH] migrating instruction generation logic to pxt --- sim/dalboard.ts | 4 +- sim/instructions.ts | 646 ++------------------------------------- sim/visuals/boardview.ts | 23 +- 3 files changed, 41 insertions(+), 632 deletions(-) diff --git a/sim/dalboard.ts b/sim/dalboard.ts index 1899b481..b888a7bc 100644 --- a/sim/dalboard.ts +++ b/sim/dalboard.ts @@ -106,7 +106,9 @@ namespace pxsim { maxWidth: "100%", maxHeight: "100%", }; - const viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView(opts), opts); + const viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView({ + visual: boardDef.visual + }), opts); document.body.innerHTML = ""; // clear children document.body.appendChild(viewHost.getView()); diff --git a/sim/instructions.ts b/sim/instructions.ts index 71f7eec3..23a0c1cc 100644 --- a/sim/instructions.ts +++ b/sim/instructions.ts @@ -8,575 +8,33 @@ import pxtrunner = pxt.runner; import pxtdocs = pxt.docs; namespace pxsim.instructions { - const LOC_LBL_SIZE = 10; - const QUANT_LBL_SIZE = 30; - const QUANT_LBL = (q: number) => `${q}x`; - const WIRE_QUANT_LBL_SIZE = 20; - const LBL_VERT_PAD = 3; - const LBL_RIGHT_PAD = 5; - const LBL_LEFT_PAD = 5; - const REQ_WIRE_HEIGHT = 45; - const REQ_CMP_HEIGHT = 55; - const REQ_CMP_SCALE = 0.5 * 3; - type Orientation = "landscape" | "portrait"; - const ORIENTATION: Orientation = "portrait"; - const PPI = 96.0; - const PAGE_SCALAR = 0.95; - const [FULL_PAGE_WIDTH, FULL_PAGE_HEIGHT] - = (ORIENTATION == "portrait" ? [PPI * 8.5 * PAGE_SCALAR, PPI * 11.0 * PAGE_SCALAR] : [PPI * 11.0 * PAGE_SCALAR, PPI * 8.5 * PAGE_SCALAR]); - const PAGE_MARGIN = PPI * 0.45; - const PAGE_WIDTH = FULL_PAGE_WIDTH - PAGE_MARGIN * 2; - const PAGE_HEIGHT = FULL_PAGE_HEIGHT - PAGE_MARGIN * 2; - const BORDER_COLOR = "gray"; - const BORDER_RADIUS = 5 * 4; - const BORDER_WIDTH = 2 * 2; - const [PANEL_ROWS, PANEL_COLS] = [1, 1]; - const PANEL_MARGIN = 20; - const PANEL_PADDING = 8 * 3; - const PANEL_WIDTH = PAGE_WIDTH / PANEL_COLS - (PANEL_MARGIN + PANEL_PADDING + BORDER_WIDTH) * PANEL_COLS; - const PANEL_HEIGHT = PAGE_HEIGHT / PANEL_ROWS - (PANEL_MARGIN + PANEL_PADDING + BORDER_WIDTH) * PANEL_ROWS; - const BOARD_WIDTH = 465; - const BOARD_LEFT = (PANEL_WIDTH - BOARD_WIDTH) / 2.0 + PANEL_PADDING; - const BOARD_BOT = PANEL_PADDING; - const NUM_BOX_SIZE = 120; - const NUM_FONT = 80; - const NUM_MARGIN = 10; - const FRONT_PAGE_BOARD_WIDTH = 400; - const PART_SCALAR = 2.3 - const PARTS_BOARD_SCALE = 0.17; - const PARTS_BB_SCALE = 0.25; - const PARTS_CMP_SCALE = 0.3; - const PARTS_WIRE_SCALE = 0.23; - const BACK_PAGE_BOARD_WIDTH = PANEL_WIDTH - PANEL_PADDING * 1.5; - const STYLE = ` - .instr-panel { - margin: ${PANEL_MARGIN}px; - padding: ${PANEL_PADDING}px; - border-width: ${BORDER_WIDTH}px; - border-color: ${BORDER_COLOR}; - border-style: solid; - border-radius: ${BORDER_RADIUS}px; - display: inline-block; - width: ${PANEL_WIDTH}px; - height: ${PANEL_HEIGHT}px; - position: relative; - overflow: hidden; - page-break-inside: avoid; - } - .board-svg { - margin: 0 auto; - display: block; - position: absolute; - bottom: ${BOARD_BOT}px; - left: ${BOARD_LEFT}px; - } - .panel-num-outer { - position: absolute; - left: ${-BORDER_WIDTH}px; - top: ${-BORDER_WIDTH}px; - width: ${NUM_BOX_SIZE}px; - height: ${NUM_BOX_SIZE}px; - border-width: ${BORDER_WIDTH}px; - border-style: solid; - border-color: ${BORDER_COLOR}; - border-radius: ${BORDER_RADIUS}px 0 ${BORDER_RADIUS}px 0; - } - .panel-num { - margin: ${NUM_MARGIN}px 0; - text-align: center; - font-size: ${NUM_FONT}px; - } - .cmp-div { - display: inline-block; - } - .reqs-div { - margin-left: ${PANEL_PADDING + NUM_BOX_SIZE}px; - margin-top: 5px; - } - .partslist-wire, - .partslist-cmp { - margin: 10px; - } - .partslist-wire { - display: inline-block; - } - `; - - function addClass(el: HTMLElement, cls: string) { - //TODO move to library - if (el.classList) el.classList.add(cls); - //BUG: won't work if element has class that is prefix of new class - //TODO: make github issue (same issue exists svg.addClass) - else if (!el.className.indexOf(cls)) el.className += " " + cls; - } - function mkTxt(p: [number, number], txt: string, size: number) { - let el = svg.elt("text") - let [x, y] = p; - svg.hydrate(el, { x: x, y: y, style: `font-size:${size}px;` }); - el.textContent = txt; - return el; - } - type mkCmpDivOpts = { - top?: string, - topSize?: number, - right?: string, - rightSize?: number, - left?: string, - leftSize?: number, - bot?: string, - botSize?: number, - wireClr?: string, - cmpWidth?: number, - cmpHeight?: number, - cmpScale?: number, - crocClips?: boolean - }; - function mkBoardImgSvg(def: string | BoardImageDefinition): visuals.SVGElAndSize { - let boardView: visuals.BoardView; - if (def === "microbit") { - boardView = new visuals.MicrobitBoardSvg({ - theme: visuals.randomTheme() - }) - } else { - boardView = new visuals.GenericBoardSvg({ - visualDef: def - }) - } - return boardView.getView(); - } - function mkBBSvg(): visuals.SVGElAndSize { - let bb = new visuals.Breadboard({}); - return bb.getSVGAndSize(); - } - function wrapSvg(el: visuals.SVGElAndSize, opts: mkCmpDivOpts): HTMLElement { - //TODO: Refactor this function; it is too complicated. There is a lot of error-prone math being done - // to scale and place all elements which could be simplified with more forethought. - let svgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - let dims = { l: 0, t: 0, w: 0, h: 0 }; - - let cmpSvgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg"); - svgEl.appendChild(cmpSvgEl); - - cmpSvgEl.appendChild(el.el); - let cmpSvgAtts = { - "viewBox": `${el.x} ${el.y} ${el.w} ${el.h}`, - "preserveAspectRatio": "xMidYMid", - }; - dims.w = el.w; - dims.h = el.h; - let scale = (scaler: number) => { - dims.h *= scaler; - dims.w *= scaler; - (cmpSvgAtts).width = dims.w; - (cmpSvgAtts).height = dims.h; - } - if (opts.cmpScale) { - scale(opts.cmpScale) - } - if (opts.cmpWidth && opts.cmpWidth < dims.w) { - scale(opts.cmpWidth / dims.w); - } else if (opts.cmpHeight && opts.cmpHeight < dims.h) { - scale(opts.cmpHeight / dims.h) - } - svg.hydrate(cmpSvgEl, cmpSvgAtts); - let elDims = { l: dims.l, t: dims.t, w: dims.w, h: dims.h }; - - let updateL = (newL: number) => { - if (newL < dims.l) { - let extraW = dims.l - newL; - dims.l = newL; - dims.w += extraW; - } - } - let updateR = (newR: number) => { - let oldR = dims.l + dims.w; - if (oldR < newR) { - let extraW = newR - oldR; - dims.w += extraW; - } - } - let updateT = (newT: number) => { - if (newT < dims.t) { - let extraH = dims.t - newT; - dims.t = newT; - dims.h += extraH; - } - } - let updateB = (newB: number) => { - let oldB = dims.t + dims.h; - if (oldB < newB) { - let extraH = newB - oldB; - dims.h += extraH; - } - } - - //labels - let [xOff, yOff] = [-0.3, 0.3]; //HACK: these constants tweak the way "mkTxt" knows how to center the text - const txtAspectRatio = [1.4, 1.0]; - if (opts && opts.top) { - let size = opts.topSize; - let txtW = size / txtAspectRatio[0]; - let txtH = size / txtAspectRatio[1]; - let [cx, y] = [elDims.l + elDims.w / 2, elDims.t - LBL_VERT_PAD - txtH / 2]; - let lbl = visuals.mkTxt(cx, y, size, 0, opts.top, xOff, yOff); - svg.addClass(lbl, "cmp-lbl"); - svgEl.appendChild(lbl); - - let len = txtW * opts.top.length; - updateT(y - txtH / 2); - updateL(cx - len / 2); - updateR(cx + len / 2); - } - if (opts && opts.bot) { - let size = opts.botSize; - let txtW = size / txtAspectRatio[0]; - let txtH = size / txtAspectRatio[1]; - let [cx, y] = [elDims.l + elDims.w / 2, elDims.t + elDims.h + LBL_VERT_PAD + txtH / 2]; - let lbl = visuals.mkTxt(cx, y, size, 0, opts.bot, xOff, yOff); - svg.addClass(lbl, "cmp-lbl"); - svgEl.appendChild(lbl); - - let len = txtW * opts.bot.length; - updateB(y + txtH / 2); - updateL(cx - len / 2); - updateR(cx + len / 2); - } - if (opts && opts.right) { - let size = opts.rightSize; - let txtW = size / txtAspectRatio[0]; - let txtH = size / txtAspectRatio[1]; - let len = txtW * opts.right.length; - let [cx, cy] = [elDims.l + elDims.w + LBL_RIGHT_PAD + len / 2, elDims.t + elDims.h / 2]; - let lbl = visuals.mkTxt(cx, cy, size, 0, opts.right, xOff, yOff); - svg.addClass(lbl, "cmp-lbl"); - svgEl.appendChild(lbl); - - updateT(cy - txtH / 2); - updateR(cx + len / 2); - updateB(cy + txtH / 2); - } - if (opts && opts.left) { - let size = opts.leftSize; - let txtW = size / txtAspectRatio[0]; - let txtH = size / txtAspectRatio[1]; - let len = txtW * opts.left.length; - let [cx, cy] = [elDims.l - LBL_LEFT_PAD - len / 2, elDims.t + elDims.h / 2]; - let lbl = visuals.mkTxt(cx, cy, size, 0, opts.left, xOff, yOff); - svg.addClass(lbl, "cmp-lbl"); - svgEl.appendChild(lbl); - - updateT(cy - txtH / 2); - updateL(cx - len / 2); - updateB(cy + txtH / 2); - } - - let svgAtts = { - "viewBox": `${dims.l} ${dims.t} ${dims.w} ${dims.h}`, - "width": dims.w * PART_SCALAR, - "height": dims.h * PART_SCALAR, - "preserveAspectRatio": "xMidYMid", - }; - svg.hydrate(svgEl, svgAtts); - let div = document.createElement("div"); - div.appendChild(svgEl); - return div; - } - function mkCmpDiv(cmp: "wire" | PartVisualDefinition, opts: mkCmpDivOpts): HTMLElement { - let state = runtime.board as pxsim.CoreBoard; - let el: visuals.SVGElAndSize; - if (cmp == "wire") { - el = visuals.mkWirePart([0, 0], opts.wireClr || "red", opts.crocClips); - } else { - let partVis = cmp; - if (typeof partVis.builtIn == "string") { - let cnstr = state.builtinPartVisuals[partVis.builtIn]; - el = cnstr([0, 0]); - } else { - el = visuals.mkGenericPartSVG(partVis); - } - } - return wrapSvg(el, opts); - } - type BoardProps = { - boardDef: BoardDefinition, - cmpDefs: Map, - fnArgs: any, - allAlloc: AllocatorResult, - stepToWires: WireInst[][], - stepToCmps: PartInst[][] - allWires: WireInst[], - allCmps: PartInst[], - lastStep: number, - colorToWires: Map, - allWireColors: string[], - }; - function mkBoardProps(allocOpts: AllocatorOpts): BoardProps { - let allocRes = allocateDefinitions(allocOpts); - let stepToWires: WireInst[][] = []; - let stepToCmps: PartInst[][] = []; - let stepOffset = 0; - allocRes.partsAndWires.forEach(cAndWs => { - let part = cAndWs.part; - let wires = cAndWs.wires; - cAndWs.assembly.forEach((step, idx) => { - if (step.part && part) - stepToCmps[stepOffset + idx] = [part] - if (step.wireIndices && step.wireIndices.length > 0 && wires) - stepToWires[stepOffset + idx] = step.wireIndices.map(i => wires[i]) - }) - stepOffset += cAndWs.assembly.length; - }); - let numSteps = stepOffset; - let lastStep = numSteps - 1; - let allCmps = allocRes.partsAndWires.map(r => r.part).filter(p => !!p); - let allWires = allocRes.partsAndWires.map(r => r.wires || []).reduce((p, n) => p.concat(n), []); - let colorToWires: Map = {} - let allWireColors: string[] = []; - allWires.forEach(w => { - if (!colorToWires[w.color]) { - colorToWires[w.color] = []; - allWireColors.push(w.color); - } - colorToWires[w.color].push(w); - }); - return { - boardDef: allocOpts.boardDef, - cmpDefs: allocOpts.partDefs, - fnArgs: allocOpts.fnArgs, - allAlloc: allocRes, - stepToWires: stepToWires, - stepToCmps: stepToCmps, - allWires: allWires, - allCmps: allCmps, - lastStep: lastStep, - colorToWires: colorToWires, - allWireColors: allWireColors, - }; - } - function mkBlankBoardAndBreadboard(boardDef: BoardDefinition, cmpDefs: Map, fnArgs: any, width: number, buildMode: boolean = false): visuals.BoardHost { - const state = runtime.board as pxsim.CoreBoard; - const opts : visuals.BoardHostOpts = { - state: state, - boardDef: boardDef, - forceBreadboard: true, - partDefs: cmpDefs, - maxWidth: `${width}px`, - fnArgs: fnArgs, - wireframe: buildMode, - }; - let boardHost = new visuals.BoardHost(pxsim.visuals.mkBoardView(opts), opts); - let view = boardHost.getView(); - svg.addClass(view, "board-svg"); - - //set smiley - //HACK - // let img = board.board.displayCmp.image; - // img.set(1, 0, 255); - // img.set(3, 0, 255); - // img.set(0, 2, 255); - // img.set(1, 3, 255); - // img.set(2, 3, 255); - // img.set(3, 3, 255); - // img.set(4, 2, 255); - // board.updateState(); - - return boardHost; - } - function drawSteps(board: visuals.BoardHost, step: number, props: BoardProps) { - let view = board.getView(); - if (step > 0) { - svg.addClass(view, "grayed"); - } - - for (let i = 0; i <= step; i++) { - let cmps = props.stepToCmps[i]; - if (cmps) { - cmps.forEach(partInst => { - let cmp = board.addPart(partInst) - //last step - if (i === step) { - //highlight locations pins - partInst.breadboardConnections.forEach(bbLoc => board.highlightBreadboardPin(bbLoc)); - svg.addClass(cmp.element, "notgrayed"); - } - }); - } - - let wires = props.stepToWires[i]; - if (wires) { - wires.forEach(w => { - let wire = board.addWire(w) - //last step - if (i === step) { - //location highlights - if (w.start.type == "breadboard") { - let lbls = board.highlightBreadboardPin((w.start)); - } else { - board.highlightBoardPin((w.start).pin); - } - if (w.end.type == "breadboard") { - let lbls = board.highlightBreadboardPin((w.end)); - } else { - board.highlightBoardPin((w.end).pin); - } - //highlight wire - board.highlightWire(wire); - } - }); - } - } - } - function mkPanel() { - //panel - let panel = document.createElement("div"); - addClass(panel, "instr-panel"); - - return panel; - } - function mkPartsPanel(props: BoardProps) { - let panel = mkPanel(); - - // board and breadboard - let boardImg = mkBoardImgSvg(props.boardDef.visual); - let board = wrapSvg(boardImg, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BOARD_SCALE }); - panel.appendChild(board); - let bbRaw = mkBBSvg(); - let bb = wrapSvg(bbRaw, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BB_SCALE }); - panel.appendChild(bb); - - // components - let cmps = props.allCmps; - cmps.forEach(c => { - let quant = 1; - // TODO: don't special case this - if (c.visual.builtIn === "buttonpair") { - quant = 2; - } - let cmp = mkCmpDiv(c.visual, { - left: QUANT_LBL(quant), - leftSize: QUANT_LBL_SIZE, - cmpScale: PARTS_CMP_SCALE, - }); - addClass(cmp, "partslist-cmp"); - panel.appendChild(cmp); - }); - - // wires - props.allWireColors.forEach(clr => { - let quant = props.colorToWires[clr].length; - let cmp = mkCmpDiv("wire", { - left: QUANT_LBL(quant), - leftSize: WIRE_QUANT_LBL_SIZE, - wireClr: clr, - cmpScale: PARTS_WIRE_SCALE, - crocClips: props.boardDef.useCrocClips - }) - addClass(cmp, "partslist-wire"); - panel.appendChild(cmp); - }) - - return panel; - } - function mkStepPanel(step: number, props: BoardProps) { - let panel = mkPanel(); - - //board - let board = mkBlankBoardAndBreadboard(props.boardDef, props.cmpDefs, props.fnArgs, BOARD_WIDTH, true) - drawSteps(board, step, props); - panel.appendChild(board.getView()); - - //number - let numDiv = document.createElement("div"); - addClass(numDiv, "panel-num-outer"); - addClass(numDiv, "noselect"); - panel.appendChild(numDiv) - let num = document.createElement("div"); - addClass(num, "panel-num"); - num.textContent = (step + 1) + ""; - numDiv.appendChild(num) - - // add requirements - let reqsDiv = document.createElement("div"); - addClass(reqsDiv, "reqs-div") - panel.appendChild(reqsDiv); - let wires = (props.stepToWires[step] || []); - let mkLabel = (loc: Loc) => { - if (loc.type === "breadboard") { - let {row, col} = (loc); - return `(${row},${col})` - } else - return (loc).pin; - }; - wires.forEach(w => { - let cmp = mkCmpDiv("wire", { - top: mkLabel(w.end), - topSize: LOC_LBL_SIZE, - bot: mkLabel(w.start), - botSize: LOC_LBL_SIZE, - wireClr: w.color, - cmpHeight: REQ_WIRE_HEIGHT, - crocClips: props.boardDef.useCrocClips - }) - addClass(cmp, "cmp-div"); - reqsDiv.appendChild(cmp); - }); - let cmps = (props.stepToCmps[step] || []); - cmps.forEach(c => { - let locs: BBLoc[]; - if (c.visual.builtIn === "buttonpair") { - //TODO: don't special case this - locs = [c.breadboardConnections[0], c.breadboardConnections[2]] - } else { - locs = [c.breadboardConnections[0]]; - } - locs.forEach((l, i) => { - let topLbl: string; - if (l) { - let {row, col} = l; - topLbl = `(${row},${col})`; - } else { - topLbl = ""; - } - let cmp = mkCmpDiv(c.visual, { - top: topLbl, - topSize: LOC_LBL_SIZE, - cmpHeight: REQ_CMP_HEIGHT, - cmpScale: REQ_CMP_SCALE - }) - addClass(cmp, "cmp-div"); - reqsDiv.appendChild(cmp); - }); - }); - - return panel; - } - function updateFrontPanel(props: BoardProps): [HTMLElement, BoardProps] { - let panel = document.getElementById("front-panel"); - - let board = mkBlankBoardAndBreadboard(props.boardDef, props.cmpDefs, props.fnArgs, FRONT_PAGE_BOARD_WIDTH, false); - board.addAll(props.allAlloc); - panel.appendChild(board.getView()); - - return [panel, props]; - } - function mkFinalPanel(props: BoardProps) { - - let panel = mkPanel(); - addClass(panel, "back-panel"); - let board = mkBlankBoardAndBreadboard(props.boardDef, props.cmpDefs, props.fnArgs, BACK_PAGE_BOARD_WIDTH, false) - board.addAll(props.allAlloc); - panel.appendChild(board.getView()); - - return panel; - } export function drawInstructions() { + pxsim.visuals.mkBoardView = (opts: pxsim.visuals.BoardViewOptions): pxsim.visuals.BoardView => { + return new visuals.MicrobitBoardSvg({ + runtime: runtime, + theme: visuals.randomTheme(), + disableTilt: false, + wireframe: opts.wireframe, + }); + } + let getQsVal = parseQueryString(); //project name let name = getQsVal("name") || "Untitled"; - if (name) { - $("#proj-title").text(name); - } + + // board def + const boardDef = JSON.parse(getQsVal("board")) as pxsim.BoardDefinition; + + //parts list + let parts = (getQsVal("parts") || "").split(" "); + parts.sort(); + + // parts definitions + let partDefinitions = JSON.parse(getQsVal("partdefs") || "{}") as pxsim.Map + + //fn args + let fnArgs = JSON.parse((getQsVal("fnArgs") || "{}")); //project code let tsCode = getQsVal("code"); @@ -615,62 +73,20 @@ ${tsPackage} }); } - // board def - const boardDef = JSON.parse(getQsVal("board")) as pxsim.BoardDefinition; - //parts list - let parts = (getQsVal("parts") || "").split(" "); - parts.sort(); - - // parts definitions - let partDefinitions = JSON.parse(getQsVal("partdefs") || "{}") as pxsim.Map - - //fn args - let fnArgs = JSON.parse((getQsVal("fnArgs") || "{}")); + if (name) + $("#proj-title").text(name); //init runtime - const COMP_CODE = ""; if (!pxsim.initCurrentRuntime) pxsim.initCurrentRuntime = initRuntimeWithDalBoard; - pxsim.runtime = new Runtime(COMP_CODE); - pxsim.runtime.board = null; - pxsim.initCurrentRuntime(); - let style = document.createElement("style"); - document.head.appendChild(style); - - style.textContent += STYLE; - - const cmpDefs = partDefinitions; - - //props - let dummyBreadboard = new visuals.Breadboard({}); - let onboardCmps = boardDef.onboardComponents || []; - let activeComponents = (parts || []).filter(c => onboardCmps.indexOf(c) < 0); - activeComponents.sort(); - let props = mkBoardProps({ - boardDef: boardDef, - partDefs: cmpDefs, - partsList: activeComponents, - fnArgs: fnArgs, - getBBCoord: dummyBreadboard.getCoord.bind(dummyBreadboard) - }); - - //front page - let frontPanel = updateFrontPanel(props); - - //all required parts - let partsPanel = mkPartsPanel(props); - document.body.appendChild(partsPanel); - - //steps - for (let s = 0; s <= props.lastStep; s++) { - let p = mkStepPanel(s, props); - document.body.appendChild(p); - } - - //final - let finalPanel = mkFinalPanel(props); - document.body.appendChild(finalPanel); + renderParts({ + name, + boardDef, + parts, + partDefinitions, + fnArgs + }) } } \ No newline at end of file diff --git a/sim/visuals/boardview.ts b/sim/visuals/boardview.ts index 0bdc3d75..3691f9db 100644 --- a/sim/visuals/boardview.ts +++ b/sim/visuals/boardview.ts @@ -1,19 +1,10 @@ namespace pxsim.visuals { - export function mkBoardView(opts: BoardHostOpts): BoardView { - if (opts.boardDef.visual === "microbit") { - return new visuals.MicrobitBoardSvg({ - runtime: runtime, - theme: visuals.randomTheme(), - disableTilt: false, - wireframe: opts.wireframe, - }); - } else { - let boardVis = opts.boardDef.visual as BoardImageDefinition; - return new visuals.GenericBoardSvg({ - visualDef: boardVis, - wireframe: opts.wireframe, - }); - } - + mkBoardView = (opts: BoardViewOptions): BoardView => { + return new visuals.MicrobitBoardSvg({ + runtime: runtime, + theme: visuals.randomTheme(), + disableTilt: false, + wireframe: opts.wireframe, + }); } } \ No newline at end of file