Compare commits
1 Commits
master
...
users/GitH
Author | SHA1 | Date | |
---|---|---|---|
|
82671e5c27 |
@ -1,3 +1,3 @@
|
||||
{
|
||||
"appref": "v1.4"
|
||||
"appref": "v1.4.24"
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { canUseWebSerial, enableWebSerialAsync } from "./deploy";
|
||||
import { projectView } from "./extension";
|
||||
|
||||
@ -53,12 +52,11 @@ function explainWebSerialPairingAsync(): Promise<void> {
|
||||
|
||||
export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (options: any) => Promise<number>): Promise<void> {
|
||||
confirmAsync = _confirmAsync;
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/cc848897.aspx
|
||||
// "For security reasons, data URIs are restricted to downloaded resources.
|
||||
// Data URIs cannot be used for navigation, for scripting, or to populate frame or iframe elements"
|
||||
const downloadAgain = !pxt.BrowserUtils.isIE() && !pxt.BrowserUtils.isEdge();
|
||||
const docUrl = (pxt.appTarget.appTheme.usbDocs ? pxt.appTarget.appTheme.usbDocs : false);
|
||||
const docUrl = pxt.appTarget.appTheme.usbDocs;
|
||||
|
||||
const jsx =
|
||||
<div className="ui grid stackable">
|
||||
@ -120,7 +118,7 @@ export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (o
|
||||
hideAgree: false,
|
||||
agreeLbl: lf("I got it"),
|
||||
className: 'downloaddialog',
|
||||
buttons: [canUseWebSerial() && {
|
||||
buttons: [canUseWebSerial() ? {
|
||||
label: lf("Bluetooth"),
|
||||
icon: "bluetooth",
|
||||
className: "bluetooth focused",
|
||||
@ -129,18 +127,18 @@ export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (o
|
||||
explainWebSerialPairingAsync()
|
||||
.then(() => enableWebSerialAndCompileAsync())
|
||||
}
|
||||
}, downloadAgain && {
|
||||
} : undefined, downloadAgain ? {
|
||||
label: fn,
|
||||
icon: "download",
|
||||
className: "lightgrey focused",
|
||||
url,
|
||||
fileName: fn
|
||||
}, docUrl && {
|
||||
} : undefined, docUrl ? {
|
||||
label: lf("Help"),
|
||||
icon: "help",
|
||||
className: "lightgrey",
|
||||
url: docUrl
|
||||
}]
|
||||
} : undefined]
|
||||
//timeout: 20000
|
||||
}).then(() => { });
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"target": "es5",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
|
@ -2,7 +2,6 @@
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
||||
|
||||
import { FieldPorts } from "./field_ports";
|
||||
import { FieldMotors } from "./field_motors";
|
||||
import { FieldBrickButtons } from "./field_brickbuttons";
|
||||
import { FieldColorEnum } from "./field_color";
|
||||
import { FieldMusic } from "./field_music";
|
||||
@ -14,9 +13,6 @@ pxt.editor.initFieldExtensionsAsync = function (opts: pxt.editor.FieldExtensionO
|
||||
fieldEditors: [{
|
||||
selector: "ports",
|
||||
editor: FieldPorts
|
||||
}, {
|
||||
selector: "motors",
|
||||
editor: FieldMotors
|
||||
}, {
|
||||
selector: "brickbuttons",
|
||||
editor: FieldBrickButtons
|
||||
|
@ -120,17 +120,20 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.
|
||||
|
||||
Blockly.DropDownDiv.setColour('#ffffff', '#dddddd');
|
||||
|
||||
// Position based on the field position.
|
||||
Blockly.DropDownDiv.showPositionedByField(this, this.onHide_.bind(this));
|
||||
|
||||
// Update colour to look selected.
|
||||
let source = this.sourceBlock_ as Blockly.BlockSvg;
|
||||
this.savedPrimary_ = source?.getColour();
|
||||
if (source?.isShadow()) {
|
||||
source.setColour(source.getColourTertiary());
|
||||
} else if (this.borderRect_) {
|
||||
this.borderRect_.setAttribute('fill', (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary());
|
||||
}
|
||||
// Calculate positioning based on the field position.
|
||||
let scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
|
||||
let bBox = { width: this.size_.width, height: this.size_.height };
|
||||
bBox.width *= scale;
|
||||
bBox.height *= scale;
|
||||
let position = this.fieldGroup_.getBoundingClientRect();
|
||||
let primaryX = position.left + bBox.width / 2;
|
||||
let primaryY = position.top + bBox.height;
|
||||
let secondaryX = primaryX;
|
||||
let secondaryY = position.top;
|
||||
// Set bounds to workspace; show the drop-down.
|
||||
(Blockly.DropDownDiv as any).setBoundsElement((<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).getParentSvg().parentNode);
|
||||
(Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY,
|
||||
this.onHide_.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -154,12 +157,5 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.
|
||||
content.removeAttribute('aria-haspopup');
|
||||
content.removeAttribute('aria-activedescendant');
|
||||
(content as HTMLElement).style.width = '';
|
||||
// Update color (deselect) on dropdown hide
|
||||
let source = this.sourceBlock_ as Blockly.BlockSvg;
|
||||
if (source?.isShadow()) {
|
||||
source.setColour(this.savedPrimary_);
|
||||
} else if (this.borderRect_) {
|
||||
this.borderRect_.setAttribute('fill', this.savedPrimary_);
|
||||
}
|
||||
};
|
||||
}
|
@ -5,14 +5,10 @@ export interface FieldColorEnumOptions extends pxtblockly.FieldColourNumberOptio
|
||||
}
|
||||
|
||||
export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Blockly.FieldCustom {
|
||||
|
||||
public isFieldCustom_ = true;
|
||||
private paramsData: any[];
|
||||
|
||||
constructor(text: string, params: FieldColorEnumOptions, opt_validator?: Function) {
|
||||
super(text, params, opt_validator);
|
||||
|
||||
this.paramsData = params["data"];
|
||||
}
|
||||
|
||||
mapColour(enumString: string) {
|
||||
@ -37,21 +33,11 @@ export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Block
|
||||
case 'ColorSensorColor.Red': return '#f12a21';
|
||||
case 'ColorSensorColor.White': return '#ffffff';
|
||||
case 'ColorSensorColor.Brown': return '#6c2d00';
|
||||
case 'ColorSensorColor.None': return '#dfe6e9';
|
||||
case 'ColorSensorColor.None': return '#dfe6e9'; // Grey
|
||||
default: return colorString;
|
||||
}
|
||||
}
|
||||
|
||||
showEditor_() {
|
||||
super.showEditor_();
|
||||
const colorCells = document.querySelectorAll('.legoColorPicker td');
|
||||
colorCells.forEach((cell) => {
|
||||
const titleName = this.mapColour(cell.getAttribute("title"));
|
||||
const index = this.paramsData.findIndex(item => item[1] === titleName);
|
||||
cell.setAttribute("title", this.paramsData[index][0]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current colour.
|
||||
* @param {boolean} opt_asHex optional field if the returned value should be a hex
|
||||
|
@ -1,133 +0,0 @@
|
||||
/// <reference path="../node_modules/pxt-core/localtypings/blockly.d.ts"/>
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtblocks.d.ts"/>
|
||||
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
||||
|
||||
export interface FieldMotorsOptions extends pxtblockly.FieldImagesOptions {
|
||||
columns?: string;
|
||||
width?: string;
|
||||
//sort?: boolean;
|
||||
}
|
||||
|
||||
export class FieldMotors extends pxtblockly.FieldImages implements Blockly.FieldCustom {
|
||||
public isFieldCustom_ = true;
|
||||
//public shouldSort_: boolean;
|
||||
|
||||
constructor(text: string, options: FieldMotorsOptions, validator?: Function) {
|
||||
super(text, options, validator);
|
||||
|
||||
this.columns_ = parseInt(options.columns) || 4;
|
||||
this.width_ = parseInt(options.width) || 400;
|
||||
//this.shouldSort_ = options.sort;
|
||||
this.addLabel_ = true;
|
||||
|
||||
this.renderSelectedImage_ = Blockly.FieldDropdown.prototype.renderSelectedText_;
|
||||
this.updateSize_ = (Blockly.Field as any).prototype.updateSize_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a dropdown menu under the text.
|
||||
* @private
|
||||
*/
|
||||
public showEditor_() {
|
||||
// If there is an existing drop-down we own, this is a request to hide the drop-down.
|
||||
if (Blockly.DropDownDiv.hideIfOwner(this)) {
|
||||
return;
|
||||
}
|
||||
let sourceBlock = this.sourceBlock_ as Blockly.BlockSvg;
|
||||
// If there is an existing drop-down someone else owns, hide it immediately and clear it.
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
Blockly.DropDownDiv.clearContent();
|
||||
// Populate the drop-down with the icons for this field.
|
||||
let dropdownDiv = Blockly.DropDownDiv.getContentDiv();
|
||||
let contentDiv = document.createElement('div');
|
||||
// Accessibility properties
|
||||
contentDiv.setAttribute('role', 'menu');
|
||||
contentDiv.setAttribute('aria-haspopup', 'true');
|
||||
const options = this.getOptions();
|
||||
//if (this.shouldSort_) options.sort();
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
const content = (options[i] as any)[0]; // Human-readable text or image.
|
||||
const value = (options[i] as any)[1]; // Language-neutral value.
|
||||
// Icons with the type property placeholder take up space but don't have any functionality
|
||||
// Use for special-case layouts
|
||||
if (content.type == 'placeholder') {
|
||||
let placeholder = document.createElement('span');
|
||||
placeholder.setAttribute('class', 'blocklyDropDownPlaceholder');
|
||||
placeholder.style.width = content.width + 'px';
|
||||
placeholder.style.height = content.height + 'px';
|
||||
contentDiv.appendChild(placeholder);
|
||||
continue;
|
||||
}
|
||||
let button = document.createElement('button');
|
||||
button.setAttribute('id', ':' + i); // For aria-activedescendant
|
||||
button.setAttribute('role', 'menuitem');
|
||||
button.setAttribute('class', 'blocklyDropDownButton');
|
||||
button.title = content.alt;
|
||||
if ((this as any).columns_) {
|
||||
button.style.width = (((this as any).width_ / (this as any).columns_) - 8) + 'px';
|
||||
//button.style.height = ((this.width_ / this.columns_) - 8) + 'px';
|
||||
} else {
|
||||
button.style.width = content.width + 'px';
|
||||
button.style.height = content.height + 'px';
|
||||
}
|
||||
let backgroundColor = sourceBlock.getColour();
|
||||
if (value == this.getValue()) {
|
||||
// This icon is selected, show it in a different colour
|
||||
backgroundColor = sourceBlock.getColourTertiary();
|
||||
button.setAttribute('aria-selected', 'true');
|
||||
}
|
||||
button.style.backgroundColor = backgroundColor;
|
||||
button.style.borderColor = sourceBlock.getColourTertiary();
|
||||
Blockly.bindEvent_(button, 'click', this, this.buttonClick_);
|
||||
Blockly.bindEvent_(button, 'mouseover', button, function () {
|
||||
this.setAttribute('class', 'blocklyDropDownButton blocklyDropDownButtonHover');
|
||||
contentDiv.setAttribute('aria-activedescendant', this.id);
|
||||
});
|
||||
Blockly.bindEvent_(button, 'mouseout', button, function () {
|
||||
this.setAttribute('class', 'blocklyDropDownButton');
|
||||
contentDiv.removeAttribute('aria-activedescendant');
|
||||
});
|
||||
let buttonImg = document.createElement('img');
|
||||
buttonImg.src = content.src;
|
||||
//buttonImg.alt = icon.alt;
|
||||
// Upon click/touch, we will be able to get the clicked element as e.target
|
||||
// Store a data attribute on all possible click targets so we can match it to the icon.
|
||||
button.setAttribute('data-value', value);
|
||||
buttonImg.setAttribute('data-value', value);
|
||||
button.appendChild(buttonImg);
|
||||
if (this.addLabel_) {
|
||||
const buttonText = this.createTextNode_(content.alt);
|
||||
buttonText.setAttribute('data-value', value);
|
||||
buttonText.style.whiteSpace = 'inherit';
|
||||
buttonText.style.width = 'auto';
|
||||
buttonText.style.padding = '0 10px';
|
||||
button.appendChild(buttonText);
|
||||
}
|
||||
contentDiv.appendChild(button);
|
||||
}
|
||||
contentDiv.style.width = (this as any).width_ + 'px';
|
||||
dropdownDiv.appendChild(contentDiv);
|
||||
|
||||
Blockly.DropDownDiv.setColour(sourceBlock.getColour(), sourceBlock.getColourTertiary());
|
||||
|
||||
// Position based on the field position.
|
||||
Blockly.DropDownDiv.showPositionedByField(this, this.onHideCallback.bind(this));
|
||||
|
||||
// Update colour to look selected.
|
||||
this.savedPrimary_ = sourceBlock?.getColour();
|
||||
if (sourceBlock?.isShadow()) {
|
||||
sourceBlock.setColour(sourceBlock.style.colourTertiary);
|
||||
} else if (this.borderRect_) {
|
||||
this.borderRect_.setAttribute('fill', sourceBlock.style.colourTertiary);
|
||||
}
|
||||
}
|
||||
|
||||
trimOptions_() {
|
||||
}
|
||||
|
||||
protected buttonClick_ = function (e: any) {
|
||||
let value = e.target.getAttribute('data-value');
|
||||
this.setValue(value);
|
||||
Blockly.DropDownDiv.hide();
|
||||
};
|
||||
}
|
@ -11,7 +11,6 @@ declare const pxtTargetBundle: any;
|
||||
|
||||
let soundCache: any;
|
||||
let soundIconCache: any;
|
||||
let soundIconCacheArray: any;
|
||||
|
||||
export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldCustom {
|
||||
public isFieldCustom_ = true;
|
||||
@ -24,7 +23,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
super(text, { blocksInfo: options.blocksInfo, sort: true, data: options.data }, validator);
|
||||
|
||||
this.columns_ = parseInt(options.columns) || 4;
|
||||
this.width_ = parseInt(options.width) || 450;
|
||||
this.width_ = parseInt(options.width) || 380;
|
||||
|
||||
this.setText = Blockly.FieldDropdown.prototype.setText;
|
||||
this.updateSize_ = (Blockly.Field as any).prototype.updateSize_;
|
||||
@ -34,7 +33,6 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
}
|
||||
if (!soundIconCache) {
|
||||
soundIconCache = JSON.parse(pxtTargetBundle.bundledpkgs['music']['icons.jres']);
|
||||
soundIconCacheArray = Object.entries(soundIconCache).filter(el => el[0] !== "*");
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,17 +49,14 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
Blockly.DropDownDiv.clearContent();
|
||||
// Populate the drop-down with the icons for this field.
|
||||
let dropdownDiv = Blockly.DropDownDiv.getContentDiv() as HTMLElement;
|
||||
let dropdownDiv = Blockly.DropDownDiv.getContentDiv();
|
||||
let contentDiv = document.createElement('div');
|
||||
// Accessibility properties
|
||||
contentDiv.setAttribute('role', 'menu');
|
||||
contentDiv.setAttribute('aria-haspopup', 'true');
|
||||
contentDiv.className = 'blocklyMusicFieldOptions';
|
||||
contentDiv.style.display = "flex";
|
||||
contentDiv.style.flexWrap = "wrap";
|
||||
contentDiv.style.float = "none";
|
||||
const options = this.getOptions();
|
||||
//options.sort(); // Do not need to use to not apply sorting in different languages
|
||||
options.sort();
|
||||
|
||||
// Create categoies
|
||||
const categories = this.getCategories(options);
|
||||
@ -72,7 +67,8 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
// Accessibility properties
|
||||
categoriesDiv.setAttribute('role', 'menu');
|
||||
categoriesDiv.setAttribute('aria-haspopup', 'true');
|
||||
categoriesDiv.style.backgroundColor = (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary();
|
||||
// FIXME: tertiary color?
|
||||
categoriesDiv.style.backgroundColor = this.sourceBlock_.getColour();
|
||||
categoriesDiv.className = 'blocklyMusicFieldCategories';
|
||||
|
||||
this.refreshCategories(categoriesDiv, categories);
|
||||
@ -86,18 +82,31 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
dropdownDiv.appendChild(categoriesDiv);
|
||||
dropdownDiv.appendChild(contentDiv);
|
||||
|
||||
Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary());
|
||||
|
||||
// Position based on the field position.
|
||||
Blockly.DropDownDiv.showPositionedByField(this, this.onHide_.bind(this));
|
||||
Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(),
|
||||
// FIXME: tertiary color?
|
||||
this.sourceBlock_.getColour());
|
||||
|
||||
// Calculate positioning based on the field position.
|
||||
let scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
|
||||
let bBox = { width: this.size_.width, height: this.size_.height };
|
||||
bBox.width *= scale;
|
||||
bBox.height *= scale;
|
||||
let position = this.fieldGroup_.getBoundingClientRect();
|
||||
let primaryX = position.left + bBox.width / 2;
|
||||
let primaryY = position.top + bBox.height;
|
||||
let secondaryX = primaryX;
|
||||
let secondaryY = position.top;
|
||||
// Set bounds to workspace; show the drop-down.
|
||||
(Blockly.DropDownDiv as any).setBoundsElement((<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).getParentSvg().parentNode);
|
||||
(Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY,
|
||||
this.onHide_.bind(this));
|
||||
|
||||
// Update colour to look selected.
|
||||
let source = this.sourceBlock_ as Blockly.BlockSvg;
|
||||
this.savedPrimary_ = source?.getColour();
|
||||
if (source?.isShadow()) {
|
||||
source.setColour(source.getColourTertiary());
|
||||
} else if (this.borderRect_) {
|
||||
this.borderRect_.setAttribute('fill', (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary());
|
||||
if (this.sourceBlock_.isShadow()) {
|
||||
this.savedPrimary_ = this.sourceBlock_.getColour();
|
||||
// FIXME
|
||||
// this.sourceBlock_.setColour(this.sourceBlock_.getColourTertiary(),
|
||||
// this.sourceBlock_.getColourSecondary(), this.sourceBlock_.getColourTertiary());
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,7 +139,6 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
backgroundColor = '#0c4e5e';
|
||||
button.setAttribute('aria-selected', 'true');
|
||||
}
|
||||
button.style.padding = "2px 6px";
|
||||
button.style.backgroundColor = backgroundColor;
|
||||
button.style.borderColor = backgroundColor;
|
||||
Blockly.bindEvent_(button, 'click', this, this.categoryClick_);
|
||||
@ -144,7 +152,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
}
|
||||
|
||||
refreshOptions(contentDiv: Element, options: any) {
|
||||
const categories = this.getCategories(options);
|
||||
|
||||
// Show options
|
||||
for (let i = 0, option: any; option = options[i]; i++) {
|
||||
let content = (options[i] as any)[0]; // Human-readable text or image.
|
||||
@ -179,11 +187,13 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
let backgroundColor = this.savedPrimary_ || this.sourceBlock_.getColour();
|
||||
if (value == this.getValue()) {
|
||||
// This icon is selected, show it in a different colour
|
||||
backgroundColor = (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary();
|
||||
// FIXME: tertiary color?
|
||||
backgroundColor = this.sourceBlock_.getColour();
|
||||
button.setAttribute('aria-selected', 'true');
|
||||
}
|
||||
button.style.backgroundColor = backgroundColor;
|
||||
button.style.borderColor = (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary();
|
||||
// FIXME: tertiary color?
|
||||
button.style.borderColor = this.sourceBlock_.getColour();
|
||||
Blockly.bindEvent_(button, 'click', this, this.buttonClick_);
|
||||
Blockly.bindEvent_(button, 'mouseup', this, this.buttonClick_);
|
||||
// These are applied manually instead of using the :hover pseudoclass
|
||||
@ -208,27 +218,15 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
this.setAttribute('class', 'blocklyDropDownButton');
|
||||
contentDiv.removeAttribute('aria-activedescendant');
|
||||
});
|
||||
|
||||
// Find index in array by category name
|
||||
const categoryIndex = categories.indexOf(category);
|
||||
|
||||
let buttonImg = document.createElement('img');
|
||||
buttonImg.src = this.getSoundIcon(categoryIndex);
|
||||
|
||||
buttonImg.src = this.getSoundIcon(category);
|
||||
//buttonImg.alt = icon.alt;
|
||||
// Upon click/touch, we will be able to get the clicked element as e.target
|
||||
// Store a data attribute on all possible click targets so we can match it to the icon.
|
||||
const textNode = this.createTextNode_(content);
|
||||
button.setAttribute('data-value', value);
|
||||
buttonImg.setAttribute('data-value', value);
|
||||
buttonImg.style.height = "auto";
|
||||
textNode.setAttribute('data-value', value);
|
||||
if (pxt.Util.userLanguage() !== "en") textNode.setAttribute('lang', pxt.Util.userLanguage()); // for hyphens, here you need to set the correct abbreviation of the selected language
|
||||
textNode.style.display = "block";
|
||||
textNode.style.lineHeight = "1rem";
|
||||
textNode.style.marginBottom = "5%";
|
||||
textNode.style.padding = "0px 8px";
|
||||
textNode.style.wordBreak = "break-word";
|
||||
textNode.style.hyphens = "auto";
|
||||
|
||||
button.appendChild(buttonImg);
|
||||
button.appendChild(textNode);
|
||||
@ -243,19 +241,12 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
super.onHide_();
|
||||
(Blockly.DropDownDiv.getContentDiv() as HTMLElement).style.maxHeight = '';
|
||||
this.stopSounds();
|
||||
// Update color (deselect) on dropdown hide
|
||||
let source = this.sourceBlock_ as Blockly.BlockSvg;
|
||||
if (source?.isShadow()) {
|
||||
source.setColour(this.savedPrimary_);
|
||||
} else if (this.borderRect_) {
|
||||
this.borderRect_.setAttribute('fill', this.savedPrimary_);
|
||||
}
|
||||
}
|
||||
|
||||
protected createTextNode_(content: string) {
|
||||
const category = this.parseCategory(content);
|
||||
let text = content.substr(content.indexOf(' ') + 1);
|
||||
|
||||
text = text.length > 15 ? text.substr(0, 12) + "..." : text;
|
||||
const textSpan = document.createElement('span');
|
||||
textSpan.setAttribute('class', 'blocklyDropdownText');
|
||||
textSpan.textContent = text;
|
||||
@ -323,9 +314,9 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
|
||||
pxsim.AudioContextManager.stop();
|
||||
}
|
||||
|
||||
private getSoundIcon(indexCategory: number) {
|
||||
if (soundIconCacheArray && soundIconCacheArray[indexCategory]) {
|
||||
return soundIconCacheArray[indexCategory][1].icon;
|
||||
private getSoundIcon(category: string) {
|
||||
if (soundIconCache && soundIconCache[category]) {
|
||||
return soundIconCache[category].icon;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"target": "es5",
|
||||
"noImplicitAny": false,
|
||||
"noImplicitReturns": true,
|
||||
"module": "commonjs",
|
||||
|
@ -250,7 +250,7 @@ namespace sensors {
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure the ambient or reflected light value from 0 (darkest) to 100 (brightest). In raw reflection light mode, the range will be different.
|
||||
* Measure the ambient or reflected light value from 0 (darkest) to 100 (brightest).
|
||||
* @param sensor the color sensor port
|
||||
*/
|
||||
//% help=sensors/color-sensor/light
|
||||
|
@ -1,3 +1,5 @@
|
||||
|
||||
|
||||
namespace sensors {
|
||||
|
||||
/**
|
||||
@ -7,9 +9,9 @@ namespace sensors {
|
||||
//% blockId=colorEnumPicker block="%color" shim=TD_ID
|
||||
//% weight=0 blockHidden=1 turnRatio.fieldOptions.decompileLiterals=1
|
||||
//% color.fieldEditor="colorenum"
|
||||
//% color.fieldOptions.colours='["#f12a21", "#ffd01b", "#006db3", "#00934b", "#000000", "#6c2d00", "#ffffff", "#dfe6e9"]'
|
||||
//% color.fieldOptions.colours='["#f12a21", "#ffd01b", "#006db3", "#00934b", "#000000", "#6c2d00", "#ffffff"]'
|
||||
//% color.fieldOptions.columns=2 color.fieldOptions.className='legoColorPicker'
|
||||
export function __colorEnumPicker(color: ColorSensorColor): number {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 4.3 KiB |
@ -195,7 +195,7 @@ namespace motors {
|
||||
* @param brake a value indicating if the motor should break when off
|
||||
*/
|
||||
//% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake=toggleOnOff"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=60 blockGap=8
|
||||
//% group="Properties"
|
||||
@ -210,7 +210,7 @@ namespace motors {
|
||||
* @param value true to pause; false to continue the program execution
|
||||
*/
|
||||
//% blockId=outputMotorSetPauseMode block="set %motor|pause on run %brake=toggleOnOff"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=60 blockGap=8
|
||||
//% group="Properties"
|
||||
@ -223,7 +223,7 @@ namespace motors {
|
||||
* Inverts the motor polarity
|
||||
*/
|
||||
//% blockId=motorSetInverted block="set %motor|inverted %reversed=toggleOnOff"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=59 blockGap=8
|
||||
//% group="Properties"
|
||||
@ -241,7 +241,7 @@ namespace motors {
|
||||
* Set the settle time after braking in milliseconds (default is 10ms).
|
||||
*/
|
||||
//% blockId=motorSetBrakeSettleTime block="set %motor|brake settle time %millis|ms"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=1 blockGap=8
|
||||
//% group="Properties"
|
||||
@ -347,7 +347,7 @@ namespace motors {
|
||||
//% blockId=motorRun block="run %motor at %speed=motorSpeedPicker|\\%||for %value %unit"
|
||||
//% weight=100 blockGap=8
|
||||
//% group="Move"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% expandableArgumentMode=toggle
|
||||
//% help=motors/motor/run
|
||||
@ -397,7 +397,7 @@ namespace motors {
|
||||
//% blockId=motorSchedule block="ramp %motor at %speed=motorSpeedPicker|\\%|for %value|%unit||accelerate %acceleration|decelerate %deceleration"
|
||||
//% weight=99 blockGap=8
|
||||
//% group="Move"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% help=motors/motor/ramp
|
||||
//% inlineInputMode=inline
|
||||
@ -427,7 +427,7 @@ namespace motors {
|
||||
* of run commands.
|
||||
*/
|
||||
//% blockId=outputMotorsetRunRamp block="set %motor|run %ramp to $value||$unit"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=21 blockGap=8
|
||||
//% group="Properties"
|
||||
@ -499,7 +499,7 @@ namespace motors {
|
||||
* @param value true for regulated motor
|
||||
*/
|
||||
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=58 blockGap=8
|
||||
//% group="Properties"
|
||||
@ -525,7 +525,7 @@ namespace motors {
|
||||
* @param timeOut optional maximum pausing time in milliseconds
|
||||
*/
|
||||
//% blockId=motorPauseUntilRead block="pause until %motor|ready"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=90 blockGap=8
|
||||
//% group="Move"
|
||||
@ -584,7 +584,7 @@ namespace motors {
|
||||
* @param motor the port which connects to the motor
|
||||
*/
|
||||
//% blockId=motorSpeed block="%motor|speed"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=72
|
||||
//% blockGap=8
|
||||
@ -600,7 +600,7 @@ namespace motors {
|
||||
* @param motor the port which connects to the motor
|
||||
*/
|
||||
//% blockId=motorAngle block="%motor|angle"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=70
|
||||
//% blockGap=8
|
||||
@ -615,7 +615,7 @@ namespace motors {
|
||||
* Clears the motor count
|
||||
*/
|
||||
//% blockId=motorClearCount block="clear %motor|counters"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=68
|
||||
//% blockGap=8
|
||||
@ -644,7 +644,7 @@ namespace motors {
|
||||
* Pauses the program until the motor is stalled.
|
||||
*/
|
||||
//% blockId=motorPauseUntilStall block="pause until %motor|stalled"
|
||||
//% motor.fieldEditor="motors"
|
||||
//% motor.fieldEditor="speed"
|
||||
//% motor.fieldOptions.decompileLiterals=1
|
||||
//% weight=89
|
||||
//% group="Move"
|
||||
@ -669,28 +669,28 @@ namespace motors {
|
||||
}
|
||||
}
|
||||
|
||||
//% whenUsed fixedInstance block="large motor A" jres=icons.motorLargePortA
|
||||
//% whenUsed fixedInstance block="large motor A" jres=icons.portA
|
||||
export const largeA = new Motor(Output.A, true);
|
||||
|
||||
//% whenUsed fixedInstance block="large motor B" jres=icons.motorLargePortB
|
||||
//% whenUsed fixedInstance block="large motor B" jres=icons.portB
|
||||
export const largeB = new Motor(Output.B, true);
|
||||
|
||||
//% whenUsed fixedInstance block="large motor C" jres=icons.motorLargePortC
|
||||
//% whenUsed fixedInstance block="large motor C" jres=icons.portC
|
||||
export const largeC = new Motor(Output.C, true);
|
||||
|
||||
//% whenUsed fixedInstance block="large motor D" jres=icons.motorLargePortD
|
||||
//% whenUsed fixedInstance block="large motor D" jres=icons.portD
|
||||
export const largeD = new Motor(Output.D, true);
|
||||
|
||||
//% whenUsed fixedInstance block="medium motor A" jres=icons.motorMeduimPortA
|
||||
//% whenUsed fixedInstance block="medium motor A" jres=icons.portA
|
||||
export const mediumA = new Motor(Output.A, false);
|
||||
|
||||
//% whenUsed fixedInstance block="medium motor B" jres=icons.motorMeduimPortB
|
||||
//% whenUsed fixedInstance block="medium motor B" jres=icons.portB
|
||||
export const mediumB = new Motor(Output.B, false);
|
||||
|
||||
//% whenUsed fixedInstance block="medium motor C" jres=icons.motorMeduimPortC
|
||||
//% whenUsed fixedInstance block="medium motor C" jres=icons.portC
|
||||
export const mediumC = new Motor(Output.C, false);
|
||||
|
||||
//% whenUsed fixedInstance block="medium motor D" jres=icons.motorMeduimPortD
|
||||
//% whenUsed fixedInstance block="medium motor D" jres=icons.portD
|
||||
export const mediumD = new Motor(Output.D, false);
|
||||
|
||||
//% fixedInstances
|
||||
@ -721,7 +721,7 @@ namespace motors {
|
||||
* @param unit (optional) unit of the value
|
||||
*/
|
||||
//% blockId=motorPairTank block="tank **motors** %motors %speedLeft=motorSpeedPicker|\\% %speedRight=motorSpeedPicker|\\%||for %value %unit"
|
||||
//% motors.fieldEditor="motors"
|
||||
//% motors.fieldEditor="ports"
|
||||
//% weight=96 blockGap=8
|
||||
//% inlineInputMode=inline
|
||||
//% group="Move"
|
||||
@ -751,7 +751,7 @@ namespace motors {
|
||||
* @param unit (optional) unit of the value
|
||||
*/
|
||||
//% blockId=motorPairSteer block="steer **motors** %chassis turn ratio %turnRatio=motorTurnRatioPicker speed %speed=motorSpeedPicker|\\%||for %value %unit"
|
||||
//% chassis.fieldEditor="motors"
|
||||
//% chassis.fieldEditor="ports"
|
||||
//% weight=95
|
||||
//% turnRatio.min=-200 turnRatio=200
|
||||
//% inlineInputMode=inline
|
||||
@ -824,16 +824,16 @@ namespace motors {
|
||||
}
|
||||
}
|
||||
|
||||
//% whenUsed fixedInstance block="large motors B+C" jres=icons.dualMotorLargePortBC
|
||||
//% whenUsed fixedInstance block="B+C" jres=icons.portBC
|
||||
export const largeBC = new SynchedMotorPair(Output.BC);
|
||||
|
||||
//% whenUsed fixedInstance block="large motors A+D" jres=icons.dualMotorLargePortAD
|
||||
//% whenUsed fixedInstance block="A+D" jres=icons.portAD
|
||||
export const largeAD = new SynchedMotorPair(Output.AD);
|
||||
|
||||
//% whenUsed fixedInstance block="large motors A+B" jres=icons.dualMotorLargePortAB
|
||||
//% whenUsed fixedInstance block="A+B" jres=icons.portAB
|
||||
export const largeAB = new SynchedMotorPair(Output.AB);
|
||||
|
||||
//% whenUsed fixedInstance block="large motors C+D" jres=icons.dualMotorLargePortCD
|
||||
//% whenUsed fixedInstance block="C+D" jres=icons.portCD
|
||||
export const largeCD = new SynchedMotorPair(Output.CD);
|
||||
|
||||
function reset(out: Output) {
|
||||
|
@ -22,7 +22,6 @@ namespace _screen_internal {
|
||||
namespace brick {
|
||||
const textOffset = 4;
|
||||
const lineOffset = 2;
|
||||
|
||||
enum ScreenMode {
|
||||
None,
|
||||
ShowLines,
|
||||
@ -30,14 +29,6 @@ namespace brick {
|
||||
Ports,
|
||||
Custom
|
||||
}
|
||||
|
||||
export enum PrintStyle {
|
||||
//% block="black on white"
|
||||
BlackOnWhite,
|
||||
//% block="white on black"
|
||||
WhiteOnBlack
|
||||
}
|
||||
|
||||
let screenMode = ScreenMode.None;
|
||||
export let font = image.font8;
|
||||
|
||||
@ -57,48 +48,6 @@ namespace brick {
|
||||
return ((screen.height - textOffset) / lineHeight()) >> 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of columns
|
||||
*/
|
||||
//%
|
||||
export function columnCount(): number {
|
||||
return ((screen.width - textOffset) / font.charWidth) >> 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Show text on the screen on a specific line and starting at a column and the selected print style.
|
||||
* @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
|
||||
* @param column the column number to print the text at (starting at 1), eg: 1
|
||||
* @param printStyle print style black on white or white on black
|
||||
*/
|
||||
//% blockId=screenPrintString block="show string $text|at line $line||column $column|style $printStyle"
|
||||
//% weight=98 group="Screen" inlineInputMode="inline" blockGap=8
|
||||
//% expandableArgumentMode="enabled"
|
||||
//% help=brick/show-string
|
||||
//% line.min=1 line.max=12
|
||||
//% column.min=1 column.max=29
|
||||
export function printString(text: string, line: number, column: number = 1, printStyle: PrintStyle = PrintStyle.BlackOnWhite) {
|
||||
if (screenMode != ScreenMode.ShowLines) {
|
||||
screenMode = ScreenMode.ShowLines;
|
||||
screen.fill(0);
|
||||
}
|
||||
|
||||
line = (line - 1) >> 0; // line indexing starts at 1
|
||||
column = (column - 1) >> 0; // column indexing starts at 1
|
||||
const nlines = lineCount();
|
||||
const nColumn = columnCount();
|
||||
if (line < 0 || line > nlines) return; // out of screen by line
|
||||
if (column < 0 || column > nColumn) return; // out of screen by column
|
||||
|
||||
const w = font.charWidth;
|
||||
const h = lineHeight();
|
||||
const x = textOffset + w * column;
|
||||
const y = textOffset + h * line;
|
||||
screen.fillRect(x, y, text.length * font.charWidth, h, (printStyle == PrintStyle.BlackOnWhite ? 0 : 255)); // clear background
|
||||
screen.print(text, x, y, (printStyle == PrintStyle.BlackOnWhite ? 1 : 2), font);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show text on the screen at a specific line.
|
||||
* @param text the text to print on the screen, eg: "Hello world"
|
||||
@ -107,8 +56,7 @@ namespace brick {
|
||||
//% 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=12
|
||||
//% deprecated=true
|
||||
//% line.min=1 line.max=10
|
||||
export function showString(text: string, line: number) {
|
||||
if (screenMode != ScreenMode.ShowLines) {
|
||||
screenMode = ScreenMode.ShowLines;
|
||||
@ -126,56 +74,19 @@ namespace brick {
|
||||
screen.print(text, textOffset, y, 1, font);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a number on the screen on a specific line and starting at a column and the selected print style.
|
||||
* @param value the numeric value
|
||||
* @param line the line number to print the text at, eg: 1
|
||||
* @param column the column number to print the text at (starting at 1), eg: 1
|
||||
* @param printStyle print style black on white or white on black
|
||||
*/
|
||||
//% blockId=screenPrintNumber block="show number $value|at line $line||column $column|style $printStyle"
|
||||
//% weight=97 group="Screen" inlineInputMode="inline" blockGap=8
|
||||
//% expandableArgumentMode="enabled"
|
||||
//% help=brick/show-number
|
||||
//% line.min=1 line.max=12
|
||||
//% column.min=1 column.max=29
|
||||
export function printNumber(value: number, line: number, column: number = 1, printStyle: PrintStyle = PrintStyle.BlackOnWhite) {
|
||||
printString("" + value, line, column, printStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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=97 group="Screen" inlineInputMode="inline" blockGap=8
|
||||
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
|
||||
//% help=brick/show-number
|
||||
//% line.min=1 line.max=12
|
||||
//% deprecated=true
|
||||
//% line.min=1 line.max=10
|
||||
export function showNumber(value: number, line: number) {
|
||||
showString("" + value, line);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a name, value pair on the screen on a specific line and starting at a column and the selected print style.
|
||||
* @param name the value name
|
||||
* @param value the numeric value
|
||||
* @param line the line number to print the text at, eg: 1
|
||||
* @param column the column number to print the text at (starting at 1), eg: 1
|
||||
* @param printStyle print style black on white or white on black
|
||||
*/
|
||||
//% blockId=screenPrintValue block="show value $name|= $value|at line $line||column $column|style $printStyle"
|
||||
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
|
||||
//% expandableArgumentMode="enabled"
|
||||
//% help=brick/show-value
|
||||
//% line.min=1 line.max=12
|
||||
//% column.min=1 column.max=29
|
||||
export function printValue(name: string, value: number, line: number, column: number = 1, printStyle: PrintStyle = PrintStyle.BlackOnWhite) {
|
||||
value = Math.round(value * 1000) / 1000;
|
||||
printString((name ? name + ": " : "") + value, line, column, printStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a name, value pair on the screen
|
||||
* @param value the numeric value
|
||||
@ -184,8 +95,7 @@ namespace brick {
|
||||
//% 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=12
|
||||
//% deprecated=true
|
||||
//% 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);
|
||||
@ -213,11 +123,11 @@ namespace brick {
|
||||
*/
|
||||
//% blockId=brickShowPorts block="show ports"
|
||||
//% help=brick/show-ports blockGap=8
|
||||
//% weight=95 group="Screen"
|
||||
//% weight=10 group="Screen"
|
||||
export function showPorts() {
|
||||
if (screenMode == ScreenMode.Ports) return;
|
||||
screenMode = ScreenMode.Ports;
|
||||
|
||||
screenMode = ScreenMode.Ports;
|
||||
renderPorts();
|
||||
control.runInParallel(function () {
|
||||
while (screenMode == ScreenMode.Ports) {
|
||||
@ -236,14 +146,11 @@ namespace brick {
|
||||
|
||||
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);
|
||||
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);
|
||||
screen.drawLine(0, h - 5 * lineHeight8, screen.width, h - 5 * lineHeight8, 1)
|
||||
|
||||
function scale(x: number) {
|
||||
if (Math.abs(x) >= 5000) {
|
||||
@ -260,9 +167,8 @@ namespace brick {
|
||||
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);
|
||||
screen.print(`${scale(data.actualSpeed)}%`, x, 3 * lineHeight8, 1, image.font8)
|
||||
screen.print(`${scale(data.count)}>`, x, 4 * lineHeight8, 1, image.font8)
|
||||
}
|
||||
|
||||
// sensors
|
||||
@ -271,16 +177,16 @@ namespace brick {
|
||||
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);
|
||||
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
|
||||
// We pause for 100ms to give time to read sensor values, so they work in on_start block
|
||||
pause(400)
|
||||
// and we're ready
|
||||
brick.setStatusLight(StatusLight.Off);
|
||||
// always show port by default if no UI is set
|
||||
@ -304,33 +210,11 @@ namespace brick {
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear on the screen at a specific line.
|
||||
* @param line the line number to clear at (starting at 1), eg: 1
|
||||
*/
|
||||
//% blockId=clearLine block="clear line $line"
|
||||
//% weight=94 group="Screen" inlineInputMode="inline" blockGap=8
|
||||
//% line.min=1 line.max=12
|
||||
export function clearLine(line: number) {
|
||||
if (screenMode != ScreenMode.ShowLines) {
|
||||
screenMode = ScreenMode.ShowLines;
|
||||
screen.fill(0);
|
||||
}
|
||||
|
||||
line = (line - 1) >> 0; // line indexing starts at 1
|
||||
const nlines = lineCount();
|
||||
if (line < 0 || line > nlines) return; // out of screen by line
|
||||
|
||||
const h = lineHeight();
|
||||
const y = textOffset + h * line;
|
||||
screen.fillRect(0, y, screen.width, h, 0); // clear background
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the screen
|
||||
*/
|
||||
//% blockId=screen_clear_screen block="clear screen"
|
||||
//% weight=93 group="Screen"
|
||||
//% weight=90 group="Screen"
|
||||
//% help=brick/clear-screen weight=1
|
||||
export function clearScreen() {
|
||||
screen.fill(0)
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pxt-ev3",
|
||||
"version": "1.4.32",
|
||||
"version": "1.4.25",
|
||||
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
|
||||
"private": false,
|
||||
"keywords": [
|
||||
@ -45,7 +45,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"pxt-common-packages": "9.2.7",
|
||||
"pxt-core": "7.2.27"
|
||||
"pxt-core": "7.2.16"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node node_modules/pxt-core/built/pxt.js travis"
|
||||
|
@ -107,10 +107,8 @@
|
||||
"driveDisplayName": "EV3",
|
||||
"boardName": "LEGO® MINDSTORMS® Education EV3",
|
||||
"copyrightText": "LEGO, the LEGO logo, MINDSTORMS and the MINDSTORMS EV3 logo are trademarks and/ or copyrights of the LEGO Group. ©2018 The LEGO Group. All rights reserved.",
|
||||
"crowdinProject": "makecode",
|
||||
"crowdinProject": "kindscript",
|
||||
"selectLanguage": true,
|
||||
"blocksCollapsing": true,
|
||||
"highContrast": true,
|
||||
"greenScreen": true,
|
||||
"availableLocales": [
|
||||
"en",
|
||||
@ -120,6 +118,7 @@
|
||||
"zh-CN",
|
||||
"fr"
|
||||
],
|
||||
"highContrast": true,
|
||||
"lightToc": true,
|
||||
"docMenu": [{
|
||||
"name": "Support",
|
||||
@ -160,10 +159,7 @@
|
||||
"extendEditor": true,
|
||||
"extendFieldEditors": true,
|
||||
"scriptManager": true,
|
||||
"debugger": true,
|
||||
"errorList": true,
|
||||
"importExtensionFiles": true,
|
||||
"addNewTypeScriptFile": true,
|
||||
"experiments": [
|
||||
"python",
|
||||
"alwaysGithubItemBlocks"
|
||||
@ -211,4 +207,4 @@
|
||||
},
|
||||
"ignoreDocsErrors": true,
|
||||
"uploadDocs": true
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ namespace pxsim {
|
||||
export class ColorSensorNode extends UartSensorNode {
|
||||
id = NodeType.ColorSensor;
|
||||
|
||||
private color: number = 0;
|
||||
private color: number = 50;
|
||||
|
||||
constructor(port: number) {
|
||||
super(port);
|
||||
@ -40,13 +40,5 @@ namespace pxsim {
|
||||
getValue() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
setMode(mode: number) {
|
||||
this.mode = mode;
|
||||
if (this.mode == ColorSensorMode.RefRaw) this.color = 512;
|
||||
else this.color = 50;
|
||||
this.changed = true;
|
||||
this.modeChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2017",
|
||||
"target": "es5",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"declaration": true,
|
||||
@ -8,8 +8,8 @@
|
||||
"rootDir": ".",
|
||||
"newLine": "LF",
|
||||
"sourceMap": false,
|
||||
"lib": ["dom", "dom.iterable", "scripthost", "es2017"],
|
||||
"lib": ["dom", "dom.iterable", "scripthost", "es6"],
|
||||
"types": [],
|
||||
"typeRoots": ["../node_modules/@types"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -241,8 +241,6 @@ namespace pxsim.visuals {
|
||||
view = new ColorGridControl(this.element, this.defs, state, port);
|
||||
} else if (state.getMode() == ColorSensorMode.Reflected) {
|
||||
view = new ColorWheelControl(this.element, this.defs, state, port);
|
||||
} else if (state.getMode() == ColorSensorMode.RefRaw) {
|
||||
view = new ColorWheelControl(this.element, this.defs, state, port);
|
||||
} else if (state.getMode() == ColorSensorMode.Ambient) {
|
||||
view = new ColorWheelControl(this.element, this.defs, state, port);
|
||||
}
|
||||
|
@ -5,8 +5,8 @@ namespace pxsim.visuals {
|
||||
export class ColorGridControl extends ControlView<ColorSensorNode> {
|
||||
private group: SVGGElement;
|
||||
|
||||
private static colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'brown', 'white', 'none'];
|
||||
private static colorValue = [5, 4, 2, 3, 1, 7, 6, 0];
|
||||
private static colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey', 'white'];
|
||||
private static colorValue = [5, 4, 2, 3, 1, 7, 6];
|
||||
|
||||
private colorDivs: Element[] = [];
|
||||
|
||||
@ -15,7 +15,7 @@ namespace pxsim.visuals {
|
||||
this.group.setAttribute("transform", `translate(2, 2.5) scale(0.6)`)
|
||||
|
||||
const colors = ['#f12a21', '#ffd01b', '#006db3', '#00934b', '#000', '#6c2d00'];
|
||||
const colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'brown'];
|
||||
const colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey'];
|
||||
|
||||
let cy = -4;
|
||||
for (let c = 0; c < colorIds.length; c++) {
|
||||
@ -33,19 +33,12 @@ namespace pxsim.visuals {
|
||||
}
|
||||
|
||||
const whiteCircleWrapper = pxsim.svg.child(this.group, "g", { 'id': 'white-cirlce-wrapper' });
|
||||
const noneCircleWrapper = pxsim.svg.child(this.group, "g", { 'id': 'nothing-circle-wrapper' });
|
||||
const whiteCircle = pxsim.svg.child(whiteCircleWrapper, "circle", { 'class': 'sim-color-grid-circle sim-color-grid-white', 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: #fff` });
|
||||
const noneCircle = pxsim.svg.child(noneCircleWrapper, "circle", { 'class': 'sim-color-grid-circle sim-color-grid-none', 'cx': 7.5, 'cy': '16', 'r': '2', 'style': `fill: #fff; fill-opacity: 0%;` });
|
||||
this.colorDivs.push(whiteCircle);
|
||||
this.colorDivs.push(noneCircle);
|
||||
pxsim.svg.child(whiteCircleWrapper, "circle", { 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: none; stroke: #94989b; stroke-width: 0.1px` });
|
||||
pxsim.svg.child(noneCircleWrapper, "circle", { 'cx': 7.5, 'cy': '16', 'r': '2', 'style': `fill: none; stroke: #94989b; stroke-width: 0.1px` });
|
||||
const circle = pxsim.svg.child(whiteCircleWrapper, "circle", { 'class': 'sim-color-grid-circle sim-color-grid-white', 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: #fff` });
|
||||
this.colorDivs.push(circle);
|
||||
pxsim.svg.child(whiteCircleWrapper, "circle", { 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: none;stroke: #94989b;stroke-width: 0.1px` });
|
||||
pointerEvents.down.forEach(evid => whiteCircleWrapper.addEventListener(evid, ev => {
|
||||
this.setColor(6);
|
||||
}));
|
||||
pointerEvents.down.forEach(evid => noneCircleWrapper.addEventListener(evid, ev => {
|
||||
this.setColor(0);
|
||||
}));
|
||||
return this.group;
|
||||
}
|
||||
|
||||
|
@ -26,12 +26,8 @@ namespace pxsim.visuals {
|
||||
return 131;
|
||||
}
|
||||
|
||||
private getMaxValue(state: ColorSensorMode) {
|
||||
return (state == ColorSensorMode.RefRaw ? 1023 : 100);
|
||||
}
|
||||
|
||||
private mapValue(x: number, inMin: number, inMax: number, outMin: number, outMax: number) {
|
||||
return (x - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
|
||||
private getMaxValue() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
updateState() {
|
||||
@ -39,12 +35,10 @@ namespace pxsim.visuals {
|
||||
return;
|
||||
}
|
||||
const node = this.state;
|
||||
const value = node.getValue();
|
||||
let inverseValue = this.getMaxValue(node.getMode()) - value;
|
||||
if (node.getMode() == ColorSensorMode.RefRaw) inverseValue = this.mapValue(inverseValue, 0, 1023, 0, 100);
|
||||
svg.setGradientValue(this.colorGradient, inverseValue + "%");
|
||||
this.reporter.textContent = `${parseFloat((value).toString()).toFixed(0)}`;
|
||||
if (node.getMode() != ColorSensorMode.RefRaw) this.reporter.textContent += `%`;
|
||||
const percentage = node.getValue();
|
||||
const inversePercentage = this.getMaxValue() - percentage;
|
||||
svg.setGradientValue(this.colorGradient, inversePercentage + "%");
|
||||
this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}%`;
|
||||
}
|
||||
|
||||
updateColorLevel(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
|
||||
@ -53,7 +47,7 @@ namespace pxsim.visuals {
|
||||
const height = bBox.height;
|
||||
let t = Math.max(0, Math.min(1, (height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height));
|
||||
const state = this.state;
|
||||
state.setColor(t * this.getMaxValue(state.getMode()));
|
||||
state.setColor(t * this.getMaxValue());
|
||||
}
|
||||
|
||||
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {
|
||||
|
@ -29,7 +29,6 @@ namespace pxsim.visuals {
|
||||
switch (mode) {
|
||||
case ColorSensorMode.Colors: this.updateSensorLightVisual('#0062DD'); return; // blue
|
||||
case ColorSensorMode.Reflected: this.updateSensorLightVisual('#F86262'); return; // red
|
||||
case ColorSensorMode.RefRaw: this.updateSensorLightVisual('#F86262'); return; // red
|
||||
case ColorSensorMode.Ambient: this.updateSensorLightVisual('#67C3E2'); return; // light blue
|
||||
}
|
||||
this.updateSensorLightVisual('#ffffff');
|
||||
|
@ -92,11 +92,6 @@
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* active toggle */
|
||||
.ui.item.editor-menuitem .active~.item.toggle {
|
||||
background: @editorToggleColor!important;
|
||||
}
|
||||
|
||||
.menubar .ui.item.editor-menuitem .item.toggle {
|
||||
height: 45px;
|
||||
}
|
||||
|