pxt-ev3/libs/screen/targetoverrides.ts
Dmitriy Antipov dd415019c4
renderPorts-extra-checks-before-print (#1020)
When the program starts, when the showBoot() function is launched, the screenMode is checked and the showPorts function is launched, which in turn executes the renderPorts() function in a loop. While renderPorts is running, the screenMode may change, for example to ShowLines (when showString() was run). It may turn out that the mode has changed, and the renderPorts method has not been fully executed ... in the future, it will draw its own graphics on the screen, although we do not expect to see them already, because. a regime change has occurred. I added checks inside the function before displaying.
2023-05-05 15:46:43 -07:00

228 lines
7.2 KiB
TypeScript

/**
* Tagged image literal converter
*/
//% shim=@f4 helper=image::ofBuffer
//% groups=["0.,","1#*"]
function img(lits: any, ...args: any[]): Image { return null }
const screen = image.create(DAL.LCD_WIDTH, DAL.LCD_HEIGHT)
namespace _screen_internal {
//% shim=pxt::updateScreen
function updateScreen(img: Image): void { }
//% shim=pxt::updateStats
function updateStats(msg: string): void { }
control.__screen.setupUpdate(() => updateScreen(screen))
control.EventContext.onStats = function (msg: string) {
updateStats(msg);
}
}
namespace brick {
const textOffset = 4;
const lineOffset = 2;
enum ScreenMode {
None,
ShowLines,
Image,
Ports,
Custom
}
let screenMode = ScreenMode.None;
export let font = image.font8;
/**
* Gets the text line height
*/
//%
export function lineHeight(): number {
return font.charHeight + lineOffset;
}
/**
* Number of lines
*/
//%
export function lineCount(): number {
return ((screen.height - textOffset) / lineHeight()) >> 0
}
/**
* Show text on the screen at a specific line.
* @param text the text to print on the screen, eg: "Hello world"
* @param line the line number to print the text at (starting at 1), eg: 1
*/
//% blockId=screen_print block="show string %text|at line %line"
//% weight=98 group="Screen" inlineInputMode="inline" blockGap=8
//% help=brick/show-string
//% line.min=1 line.max=10
export function showString(text: string, line: number) {
if (screenMode != ScreenMode.ShowLines) {
screenMode = ScreenMode.ShowLines;
screen.fill(0);
}
// line indexing starts at 1.
line = (line - 1) >> 0;
const nlines = lineCount();
if (line < 0 || line > nlines) return; // out of screen
const h = lineHeight();
const y = textOffset + h * line;
screen.fillRect(0, y, screen.width, h, 0); // clear background
screen.print(text, textOffset, y, 1, font);
}
/**
* Show a number on the screen
* @param value the numeric value
* @param line the line number to print the text at, eg: 1
*/
//% blockId=screenShowNumber block="show number %name|at line %line"
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
//% help=brick/show-number
//% line.min=1 line.max=10
export function showNumber(value: number, line: number) {
showString("" + value, line);
}
/**
* Show a name, value pair on the screen
* @param value the numeric value
* @param line the line number to print the text at, eg: 1
*/
//% blockId=screenShowValue block="show value %name|= %text|at line %line"
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
//% help=brick/show-value
//% line.min=1 line.max=10
export function showValue(name: string, value: number, line: number) {
value = Math.round(value * 1000) / 1000;
showString((name ? name + ": " : "") + value, line);
}
/**
* Show an image on the screen
* @param image image to draw
* @param duration duration in milliseconds to display the image, eg: 400
*/
//% blockId=screen_show_image block="show image %image=screen_image_picker"
//% weight=100 group="Screen" blockGap=8
//% help=brick/show-image
export function showImage(image: Image, duration: number = 400) {
if (!image) return;
screenMode = ScreenMode.Image;
screen.fill(0);
screen.drawImage(image, 0, 0);
if (duration > 0)
pause(duration);
}
/**
* Display the status of the sensors and motors attached to ports
*/
//% blockId=brickShowPorts block="show ports"
//% help=brick/show-ports blockGap=8
//% weight=10 group="Screen"
export function showPorts() {
if (screenMode == ScreenMode.Ports) return;
screenMode = ScreenMode.Ports;
renderPorts();
control.runInParallel(function () {
while (screenMode == ScreenMode.Ports) {
renderPorts();
pause(50);
}
})
}
function renderPorts() {
const col = 44;
const lineHeight8 = image.font8.charHeight + 2;
const h = screen.height;
clearScreen();
for (let i = 0; i < 4; ++i) {
const x = i * col + 2;
if (screenMode != ScreenMode.Ports) return;
screen.print("ABCD"[i], x, 1 * lineHeight8, 1, image.font8);
screen.print((i + 1).toString(), x, h - lineHeight8, 1, image.font8);
}
if (screenMode != ScreenMode.Ports) return;
screen.drawLine(0, 5 * lineHeight8, screen.width, 5 * lineHeight8, 1);
screen.drawLine(0, h - 5 * lineHeight8, screen.width, h - 5 * lineHeight8, 1);
function scale(x: number) {
if (Math.abs(x) >= 5000) {
const k = Math.floor(x / 1000);
const r = Math.round((x - 1000 * k) / 100);
return `${k}.${r}k`
}
return ("" + (x || 0));
}
// motors
const datas = motors.getAllMotorData();
for (let i = 0; i < datas.length; ++i) {
const data = datas[i];
const x = i * col + 2;
if (!data.actualSpeed && !data.count) continue;
if (screenMode != ScreenMode.Ports) return;
screen.print(`${scale(data.actualSpeed)}%`, x, 3 * lineHeight8, 1, image.font8);
screen.print(`${scale(data.count)}>`, x, 4 * lineHeight8, 1, image.font8);
}
// sensors
const sis = sensors.internal.getActiveSensors();
for (let i = 0; i < sis.length; ++i) {
const si = sis[i];
const x = (si.port() - 1) * col + 2;
const inf = si._info();
if (screenMode != ScreenMode.Ports) return;
if (inf) screen.print(inf, x, h - 2 * lineHeight8, 1, inf.length > 4 ? image.font5 : image.font8);
}
}
export function showBoot() {
// pulse green, play startup sound, turn off light
brick.setStatusLight(StatusLight.GreenPulse);
// We pause to give time to read sensor values, so they work in on_start block
pause(400); // It turns out that this time is not enough for the simulator to display the LED change
// and we're ready
brick.setStatusLight(StatusLight.Off);
// always show port by default if no UI is set
control.runInParallel(function () {
// show ports if nothing is has been shown
if (screenMode != ScreenMode.None) return;
showPorts();
})
}
/**
* An image
* @param image the image
*/
//% blockId=screen_image_picker block="%image" shim=TD_ID
//% image.fieldEditor="images"
//% image.fieldOptions.columns=6
//% image.fieldOptions.width=600
//% group="Screen" weight=0 blockHidden=1
export function __imagePicker(image: Image): Image {
return image;
}
/**
* Clear the screen
*/
//% blockId=screen_clear_screen block="clear screen"
//% weight=90 group="Screen"
//% help=brick/clear-screen weight=1
export function clearScreen() {
screen.fill(0)
}
}