Always diplay sad face on errors; use nullCheck() function; see https://github.com/Microsoft/pxt/issues/302
This commit is contained in:
parent
50293fc654
commit
61a29f7c67
@ -154,7 +154,7 @@ namespace pxsim.instructions {
|
|||||||
//TODO: Refactor this function; it is too complicated. There is a lot of error-prone math being done
|
//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.
|
// to scale and place all elements which could be simplified with more forethought.
|
||||||
let svgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
let svgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
let dims = {l: 0, t: 0, w: 0, h: 0};
|
let dims = { l: 0, t: 0, w: 0, h: 0 };
|
||||||
|
|
||||||
let cmpSvgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
let cmpSvgEl = <SVGSVGElement>document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||||
svgEl.appendChild(cmpSvgEl);
|
svgEl.appendChild(cmpSvgEl);
|
||||||
@ -181,7 +181,7 @@ namespace pxsim.instructions {
|
|||||||
scale(opts.cmpHeight / dims.h)
|
scale(opts.cmpHeight / dims.h)
|
||||||
}
|
}
|
||||||
svg.hydrate(cmpSvgEl, cmpSvgAtts);
|
svg.hydrate(cmpSvgEl, cmpSvgAtts);
|
||||||
let elDims = {l: dims.l, t: dims.t, w: dims.w, h: dims.h};
|
let elDims = { l: dims.l, t: dims.t, w: dims.w, h: dims.h };
|
||||||
|
|
||||||
let updateL = (newL: number) => {
|
let updateL = (newL: number) => {
|
||||||
if (newL < dims.l) {
|
if (newL < dims.l) {
|
||||||
@ -293,7 +293,7 @@ namespace pxsim.instructions {
|
|||||||
let cnstr = builtinComponentPartVisual[builtinVis];
|
let cnstr = builtinComponentPartVisual[builtinVis];
|
||||||
el = cnstr([0, 0]);
|
el = cnstr([0, 0]);
|
||||||
} else {
|
} else {
|
||||||
let partVis = <PartVisualDefinition> cmp;
|
let partVis = <PartVisualDefinition>cmp;
|
||||||
el = visuals.mkGenericPartSVG(partVis);
|
el = visuals.mkGenericPartSVG(partVis);
|
||||||
}
|
}
|
||||||
return wrapSvg(el, opts);
|
return wrapSvg(el, opts);
|
||||||
@ -320,7 +320,7 @@ namespace pxsim.instructions {
|
|||||||
let step = w.assemblyStep + 1;
|
let step = w.assemblyStep + 1;
|
||||||
(stepToWires[step] || (stepToWires[step] = [])).push(w)
|
(stepToWires[step] || (stepToWires[step] = [])).push(w)
|
||||||
});
|
});
|
||||||
let getMaxStep = (ns: {assemblyStep: number}[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0);
|
let getMaxStep = (ns: { assemblyStep: number }[]) => ns.reduce((m, n) => Math.max(m, n.assemblyStep), 0);
|
||||||
let stepOffset = powerWires.length > 0 ? getMaxStep(powerWires) + 2 : 1;
|
let stepOffset = powerWires.length > 0 ? getMaxStep(powerWires) + 2 : 1;
|
||||||
components.forEach(cAndWs => {
|
components.forEach(cAndWs => {
|
||||||
let {component, wires} = cAndWs;
|
let {component, wires} = cAndWs;
|
||||||
@ -451,10 +451,10 @@ namespace pxsim.instructions {
|
|||||||
|
|
||||||
// board and breadboard
|
// board and breadboard
|
||||||
let boardImg = mkBoardImgSvg(props.boardDef.visual);
|
let boardImg = mkBoardImgSvg(props.boardDef.visual);
|
||||||
let board = wrapSvg(boardImg, {left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BOARD_SCALE});
|
let board = wrapSvg(boardImg, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BOARD_SCALE });
|
||||||
panel.appendChild(board);
|
panel.appendChild(board);
|
||||||
let bbRaw = mkBBSvg();
|
let bbRaw = mkBBSvg();
|
||||||
let bb = wrapSvg(bbRaw, {left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BB_SCALE});
|
let bb = wrapSvg(bbRaw, { left: QUANT_LBL(1), leftSize: QUANT_LBL_SIZE, cmpScale: PARTS_BB_SCALE });
|
||||||
panel.appendChild(bb);
|
panel.appendChild(bb);
|
||||||
|
|
||||||
// components
|
// components
|
||||||
@ -592,7 +592,7 @@ namespace pxsim.instructions {
|
|||||||
//we use the docs renderer to decompile the code to blocks and render it
|
//we use the docs renderer to decompile the code to blocks and render it
|
||||||
//TODO: render the blocks code directly
|
//TODO: render the blocks code directly
|
||||||
let md =
|
let md =
|
||||||
`\`\`\`blocks
|
`\`\`\`blocks
|
||||||
${tsCode}
|
${tsCode}
|
||||||
\`\`\`
|
\`\`\`
|
||||||
\`\`\`package
|
\`\`\`package
|
||||||
@ -600,9 +600,9 @@ ${tsPackage}
|
|||||||
\`\`\`
|
\`\`\`
|
||||||
`
|
`
|
||||||
|
|
||||||
pxtdocs.requireMarked = function() { return (<any>window).marked; }
|
pxtdocs.requireMarked = function () { return (<any>window).marked; }
|
||||||
pxtrunner.renderMarkdownAsync(codeContainerDiv, md)
|
pxtrunner.renderMarkdownAsync(codeContainerDiv, md)
|
||||||
.done(function() {
|
.done(function () {
|
||||||
let codeSvg = $("#proj-code-container svg");
|
let codeSvg = $("#proj-code-container svg");
|
||||||
if (codeSvg.length > 0) {
|
if (codeSvg.length > 0) {
|
||||||
//code rendered successfully as blocks
|
//code rendered successfully as blocks
|
||||||
|
@ -5,14 +5,33 @@
|
|||||||
namespace pxsim {
|
namespace pxsim {
|
||||||
export type BBRowCol = [/*row*/string, /*column*/string];
|
export type BBRowCol = [/*row*/string, /*column*/string];
|
||||||
export type BoardPin = string;
|
export type BoardPin = string;
|
||||||
export interface BBLoc {type: "breadboard", rowCol: BBRowCol};
|
export interface BBLoc { type: "breadboard", rowCol: BBRowCol };
|
||||||
export interface BoardLoc {type: "dalboard", pin: BoardPin};
|
export interface BoardLoc { type: "dalboard", pin: BoardPin };
|
||||||
export type Loc = BBLoc | BoardLoc;
|
export type Loc = BBLoc | BoardLoc;
|
||||||
|
|
||||||
export function initRuntimeWithDalBoard() {
|
export function initRuntimeWithDalBoard() {
|
||||||
U.assert(!runtime.board);
|
U.assert(!runtime.board);
|
||||||
let b = new DalBoard();
|
let b = new DalBoard();
|
||||||
runtime.board = b;
|
runtime.board = b;
|
||||||
|
runtime.postError = (e) => {
|
||||||
|
led.setBrightness(255);
|
||||||
|
let img = board().ledMatrixState.image;
|
||||||
|
img.clear();
|
||||||
|
img.set(0, 4, 255);
|
||||||
|
img.set(1, 3, 255);
|
||||||
|
img.set(2, 3, 255);
|
||||||
|
img.set(3, 3, 255);
|
||||||
|
img.set(4, 4, 255);
|
||||||
|
img.set(0, 0, 255);
|
||||||
|
img.set(1, 0, 255);
|
||||||
|
img.set(0, 1, 255);
|
||||||
|
img.set(1, 1, 255);
|
||||||
|
img.set(3, 0, 255);
|
||||||
|
img.set(4, 0, 255);
|
||||||
|
img.set(3, 1, 255);
|
||||||
|
img.set(4, 1, 255);
|
||||||
|
runtime.updateDisplay();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!pxsim.initCurrentRuntime) {
|
if (!pxsim.initCurrentRuntime) {
|
||||||
pxsim.initCurrentRuntime = initRuntimeWithDalBoard;
|
pxsim.initCurrentRuntime = initRuntimeWithDalBoard;
|
||||||
@ -50,15 +69,15 @@ namespace pxsim.visuals {
|
|||||||
move: "pointermove",
|
move: "pointermove",
|
||||||
leave: "pointerleave"
|
leave: "pointerleave"
|
||||||
} : {
|
} : {
|
||||||
up: "mouseup",
|
up: "mouseup",
|
||||||
down: "mousedown",
|
down: "mousedown",
|
||||||
move: "mousemove",
|
move: "mousemove",
|
||||||
leave: "mouseleave"
|
leave: "mouseleave"
|
||||||
};
|
};
|
||||||
|
|
||||||
export function translateEl(el: SVGElement, xy: [number, number]) {
|
export function translateEl(el: SVGElement, xy: [number, number]) {
|
||||||
//TODO append translation instead of replacing the full transform
|
//TODO append translation instead of replacing the full transform
|
||||||
svg.hydrate(el, {transform: `translate(${xy[0]} ${xy[1]})`});
|
svg.hydrate(el, { transform: `translate(${xy[0]} ${xy[1]})` });
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComposeOpts {
|
export interface ComposeOpts {
|
||||||
@ -83,14 +102,14 @@ namespace pxsim.visuals {
|
|||||||
export function composeSVG(opts: ComposeOpts): ComposeResult {
|
export function composeSVG(opts: ComposeOpts): ComposeResult {
|
||||||
let [a, b] = [opts.el1, opts.el2];
|
let [a, b] = [opts.el1, opts.el2];
|
||||||
U.assert(a.x == 0 && a.y == 0 && b.x == 0 && b.y == 0, "el1 and el2 x,y offsets not supported");
|
U.assert(a.x == 0 && a.y == 0 && b.x == 0 && b.y == 0, "el1 and el2 x,y offsets not supported");
|
||||||
let setXY = (e: SVGSVGElement, x: number, y: number) => svg.hydrate(e, {x: x, y: y});
|
let setXY = (e: SVGSVGElement, x: number, y: number) => svg.hydrate(e, { x: x, y: y });
|
||||||
let setWH = (e: SVGSVGElement, w: string, h: string) => {
|
let setWH = (e: SVGSVGElement, w: string, h: string) => {
|
||||||
if (w)
|
if (w)
|
||||||
svg.hydrate(e, {width: w});
|
svg.hydrate(e, { width: w });
|
||||||
if (h)
|
if (h)
|
||||||
svg.hydrate(e, {height: h});
|
svg.hydrate(e, { height: h });
|
||||||
}
|
}
|
||||||
let setWHpx = (e: SVGSVGElement, w: number, h: number) => svg.hydrate(e, {width: `${w}px`, height: `${h}px`});
|
let setWHpx = (e: SVGSVGElement, w: number, h: number) => svg.hydrate(e, { width: `${w}px`, height: `${h}px` });
|
||||||
let scaleUnit = opts.scaleUnit2;
|
let scaleUnit = opts.scaleUnit2;
|
||||||
let aScalar = opts.scaleUnit2 / opts.scaleUnit1;
|
let aScalar = opts.scaleUnit2 / opts.scaleUnit1;
|
||||||
let bScalar = 1.0;
|
let bScalar = 1.0;
|
||||||
@ -157,11 +176,11 @@ namespace pxsim.visuals {
|
|||||||
let w = scaleFn(opts.width);
|
let w = scaleFn(opts.width);
|
||||||
let h = scaleFn(opts.height);
|
let h = scaleFn(opts.height);
|
||||||
let img = <SVGImageElement>svg.elt("image", {
|
let img = <SVGImageElement>svg.elt("image", {
|
||||||
width: w,
|
width: w,
|
||||||
height: h,
|
height: h,
|
||||||
"href": `${opts.image}`
|
"href": `${opts.image}`
|
||||||
});
|
});
|
||||||
return {el: img, w: w, h: h, x: 0, y: 0};
|
return { el: img, w: w, h: h, x: 0, y: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Coord = [number, number];
|
export type Coord = [number, number];
|
||||||
@ -190,13 +209,15 @@ namespace pxsim.visuals {
|
|||||||
|
|
||||||
export function mkTxt(cx: number, cy: number, size: number, rot: number, txt: string, txtXOffFactor?: number, txtYOffFactor?: number): SVGTextElement {
|
export function mkTxt(cx: number, cy: number, size: number, rot: number, txt: string, txtXOffFactor?: number, txtYOffFactor?: number): SVGTextElement {
|
||||||
let el = <SVGTextElement>svg.elt("text")
|
let el = <SVGTextElement>svg.elt("text")
|
||||||
//HACK: these constants (txtXOffFactor, txtYOffFactor) tweak the way this algorithm knows how to center the text
|
//HACK: these constants (txtXOffFactor, txtYOffFactor) tweak the way this algorithm knows how to center the text
|
||||||
txtXOffFactor = txtXOffFactor || -0.33333;
|
txtXOffFactor = txtXOffFactor || -0.33333;
|
||||||
txtYOffFactor = txtYOffFactor || 0.3;
|
txtYOffFactor = txtYOffFactor || 0.3;
|
||||||
const xOff = txtXOffFactor * size * txt.length;
|
const xOff = txtXOffFactor * size * txt.length;
|
||||||
const yOff = txtYOffFactor * size;
|
const yOff = txtYOffFactor * size;
|
||||||
svg.hydrate(el, {style: `font-size:${size}px;`,
|
svg.hydrate(el, {
|
||||||
transform: `translate(${cx} ${cy}) rotate(${rot}) translate(${xOff} ${yOff})` });
|
style: `font-size:${size}px;`,
|
||||||
|
transform: `translate(${cx} ${cy}) rotate(${rot}) translate(${xOff} ${yOff})`
|
||||||
|
});
|
||||||
svg.addClass(el, "noselect");
|
svg.addClass(el, "noselect");
|
||||||
el.textContent = txt;
|
el.textContent = txt;
|
||||||
return el;
|
return el;
|
||||||
|
@ -195,26 +195,24 @@ namespace pxsim.images {
|
|||||||
|
|
||||||
namespace pxsim.ImageMethods {
|
namespace pxsim.ImageMethods {
|
||||||
export function showImage(leds: Image, offset: number) {
|
export function showImage(leds: Image, offset: number) {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
|
|
||||||
leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
|
leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
|
||||||
runtime.queueDisplayUpdate()
|
runtime.queueDisplayUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function plotImage(leds: Image, offset: number): void {
|
export function plotImage(leds: Image, offset: number): void {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
|
|
||||||
leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
|
leds.copyTo(offset, 5, board().ledMatrixState.image, 0)
|
||||||
runtime.queueDisplayUpdate()
|
runtime.queueDisplayUpdate()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function height(leds: Image): number {
|
export function height(leds: Image): number {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
return Image.height;
|
return Image.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function width(leds: Image): number {
|
export function width(leds: Image): number {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
return leds.width;
|
return leds.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,35 +225,32 @@ namespace pxsim.ImageMethods {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function pixel(leds: Image, x: number, y: number): number {
|
export function pixel(leds: Image, x: number, y: number): number {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
return leds.get(x, y);
|
return leds.get(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setPixel(leds: Image, x: number, y: number, v: number) {
|
export function setPixel(leds: Image, x: number, y: number, v: number) {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
leds.set(x, y, v);
|
leds.set(x, y, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function clear(leds: Image) {
|
export function clear(leds: Image) {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
|
|
||||||
leds.clear();
|
leds.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setPixelBrightness(i: Image, x: number, y: number, b: number) {
|
export function setPixelBrightness(i: Image, x: number, y: number, b: number) {
|
||||||
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(i)
|
||||||
|
|
||||||
i.set(x, y, b);
|
i.set(x, y, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pixelBrightness(i: Image, x: number, y: number): number {
|
export function pixelBrightness(i: Image, x: number, y: number): number {
|
||||||
if (!i) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(i)
|
||||||
|
|
||||||
return i.get(x, y);
|
return i.get(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scrollImage(leds: Image, stride: number, interval: number): void {
|
export function scrollImage(leds: Image, stride: number, interval: number): void {
|
||||||
if (!leds) panic(PanicCode.MICROBIT_NULL_DEREFERENCE);
|
pxtrt.nullCheck(leds)
|
||||||
if (stride == 0) stride = 1;
|
if (stride == 0) stride = 1;
|
||||||
|
|
||||||
let cb = getResume();
|
let cb = getResume();
|
||||||
|
@ -19,24 +19,6 @@ namespace pxsim {
|
|||||||
|
|
||||||
export function panic(code: number) {
|
export function panic(code: number) {
|
||||||
console.log("PANIC:", code)
|
console.log("PANIC:", code)
|
||||||
led.setBrightness(255);
|
|
||||||
let img = board().ledMatrixState.image;
|
|
||||||
img.clear();
|
|
||||||
img.set(0, 4, 255);
|
|
||||||
img.set(1, 3, 255);
|
|
||||||
img.set(2, 3, 255);
|
|
||||||
img.set(3, 3, 255);
|
|
||||||
img.set(4, 4, 255);
|
|
||||||
img.set(0, 0, 255);
|
|
||||||
img.set(1, 0, 255);
|
|
||||||
img.set(0, 1, 255);
|
|
||||||
img.set(1, 1, 255);
|
|
||||||
img.set(3, 0, 255);
|
|
||||||
img.set(4, 0, 255);
|
|
||||||
img.set(3, 1, 255);
|
|
||||||
img.set(4, 1, 255);
|
|
||||||
runtime.updateDisplay();
|
|
||||||
|
|
||||||
throw new Error("PANIC " + code)
|
throw new Error("PANIC " + code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user