Compare commits

..

1 Commits

Author SHA1 Message Date
peli
fecfdc4c11 patching references 2020-08-07 10:08:34 -07:00
58 changed files with 710 additions and 730 deletions

View File

@ -1,40 +0,0 @@
name: pxt-buildmain
on:
push:
branches:
- 'master'
- 'main'
create:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: |
sudo apt-get install xvfb
sudo npm install -g pxt
npm install
- name: pxt ci
run: |
pxt ci
env:
CROWDIN_KEY: ${{ secrets.CROWDIN_KEY }}
PXT_ACCESS_TOKEN: ${{ secrets.PXT_ACCESS_TOKEN }}
PXT_RELEASE_REPO: ${{ secrets.PXT_RELEASE_REPO }}
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
CHROME_BIN: chromium-browser
DISPLAY: :99.0
CI: true

View File

@ -1,31 +0,0 @@
name: pxt-buildpr
on: [pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: |
sudo apt-get install xvfb
sudo npm install -g pxt
npm install
- name: pxt ci
run: |
pxt ci
env:
CHROME_BIN: chromium-browser
DISPLAY: :99.0
CI: true

View File

@ -1,39 +0,0 @@
name: pxt-buildpush
on:
push:
# main/master has its own build that includes the crowdin key
branches-ignore:
- 'main'
- 'master'
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: |
sudo apt-get install xvfb
sudo npm install -g pxt
npm install
- name: pxt ci
run: |
pxt ci
env:
PXT_ACCESS_TOKEN: ${{ secrets.PXT_ACCESS_TOKEN }}
PXT_RELEASE_REPO: ${{ secrets.PXT_RELEASE_REPO }}
NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }}
CHROME_BIN: chromium-browser
DISPLAY: :99.0
CI: true

9
.travis.yml Normal file
View File

@ -0,0 +1,9 @@
language: node_js
node_js:
- "8.9.0"
script:
- "node node_modules/pxt-core/built/pxt.js travis"
sudo: false
cache:
directories:
- node_modules

View File

@ -1,41 +0,0 @@
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
## Preferred Languages
We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
<!-- END MICROSOFT SECURITY.MD BLOCK -->

View File

@ -1,3 +1,3 @@
{ {
"appref": "v1.4" "appref": "v"
} }

View File

@ -27,6 +27,7 @@ while (true) {
music.playSoundEffectUntilDone(sounds.mechanicalMotorStart) music.playSoundEffectUntilDone(sounds.mechanicalMotorStart)
music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle); music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle);
} }
pause(1);
} }
``` ```
@ -42,5 +43,6 @@ while (true) {
music.playSoundEffectUntilDone(sounds.mechanicalMotorStart) music.playSoundEffectUntilDone(sounds.mechanicalMotorStart)
music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle); music.playSoundEffectUntilDone(sounds.mechanicalMotorIdle);
} }
pause(1);
} }
``` ```

View File

@ -1,3 +1,3 @@
{ {
"appref": "v1.2.31" "appref": "v1.2.27"
} }

View File

@ -2,16 +2,16 @@
## Example #example ## Example #example
Use a wait and the timer to generate a number. Use the a wait and the timer to generate a crazy number.
```blocks ```blocks
let something = 0 let crazy = 0
for (let i = 0; i < 100; i++) { for (let i = 0; i < 100; i++) {
control.waitMicros(100) control.waitMicros(100)
something = control.millis() crazy = control.millis()
something += control.deviceSerialNumber() crazy += control.deviceSerialNumber()
if (something != 0) { if (crazy != 0) {
something = something / 1000000 crazy = crazy / 1000000
} }
} }
``` ```

View File

@ -49,7 +49,7 @@ declare interface Serial extends EventTarget {
requestPort(options: SerialPortRequestOptions): Promise<SerialPort>; requestPort(options: SerialPortRequestOptions): Promise<SerialPort>;
} }
class WebSerialPackageIO implements pxt.packetio.PacketIO { class WebSerialPackageIO implements pxt.HF2.PacketIO {
onData: (v: Uint8Array) => void; onData: (v: Uint8Array) => void;
onError: (e: Error) => void; onError: (e: Error) => void;
onEvent: (v: Uint8Array) => void; onEvent: (v: Uint8Array) => void;
@ -87,7 +87,7 @@ class WebSerialPackageIO implements pxt.packetio.PacketIO {
} }
static portIos: WebSerialPackageIO[] = []; static portIos: WebSerialPackageIO[] = [];
static async mkPacketIOAsync(): Promise<pxt.packetio.PacketIO> { static async mkPacketIOAsync(): Promise<pxt.HF2.PacketIO> {
const serial = (<any>navigator).serial; const serial = (<any>navigator).serial;
if (serial) { if (serial) {
try { try {
@ -130,7 +130,7 @@ class WebSerialPackageIO implements pxt.packetio.PacketIO {
private async closeAsync() { private async closeAsync() {
// don't close port // don't close port
return pxt.U.delay(500); return Promise.delay(500);
} }
reconnectAsync(): Promise<void> { reconnectAsync(): Promise<void> {
@ -146,33 +146,11 @@ class WebSerialPackageIO implements pxt.packetio.PacketIO {
this._writer = this.port.writable.getWriter(); this._writer = this.port.writable.getWriter();
return this._writer.write(pkt); return this._writer.write(pkt);
} }
onDeviceConnectionChanged(connect: boolean) {
throw new Error("onDeviceConnectionChanged not implemented");
}
onConnectionChanged() {
throw new Error("onConnectionChanged not implemented");
}
isConnecting() {
throw new Error("isConnecting not implemented");
return false;
}
isConnected() {
throw new Error("isConnected not implemented");
return false;
}
disposeAsync() {
return Promise.reject("disposeAsync not implemented")
}
} }
function hf2Async() { function hf2Async() {
const pktIOAsync: Promise<pxt.packetio.PacketIO> = useWebSerial const pktIOAsync: Promise<pxt.HF2.PacketIO> = useWebSerial
? WebSerialPackageIO.mkPacketIOAsync() : pxt.packetio.mkPacketIOAsync() ? WebSerialPackageIO.mkPacketIOAsync() : pxt.HF2.mkPacketIOAsync()
return pktIOAsync.then(h => { return pktIOAsync.then(h => {
let w = new Ev3Wrapper(h) let w = new Ev3Wrapper(h)
ev3 = w ev3 = w
@ -212,19 +190,14 @@ export function enableWebSerialAsync() {
else return Promise.resolve(); else return Promise.resolve();
} }
async function cleanupAsync() { function cleanupAsync() {
if (ev3) { if (ev3) {
console.log('cleanup previous port') console.log('cleanup previous port')
try { return ev3.disconnectAsync()
await ev3.disconnectAsync() .catch(e => { })
} .finally(() => { ev3 = undefined; });
catch (e) {
}
finally {
ev3 = undefined;
}
} }
return Promise.resolve();
} }
let initPromise: Promise<Ev3Wrapper> let initPromise: Promise<Ev3Wrapper>
@ -234,7 +207,7 @@ function initHidAsync() { // needs to run within a click handler
if (useHID) { if (useHID) {
initPromise = cleanupAsync() initPromise = cleanupAsync()
.then(() => hf2Async()) .then(() => hf2Async())
.catch((err: any) => { .catch(err => {
console.error(err); console.error(err);
initPromise = null initPromise = null
useHID = false; useHID = false;
@ -311,7 +284,7 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
.catch(e => { .catch(e => {
// user easily forgets to stop robot // user easily forgets to stop robot
bluetoothTryAgainAsync().then(() => w.disconnectAsync()) bluetoothTryAgainAsync().then(() => w.disconnectAsync())
.then(() => pxt.U.delay(1000)) .then(() => Promise.delay(1000))
.then(() => w.reconnectAsync()); .then(() => w.reconnectAsync());
// nothing we can do // nothing we can do
@ -323,7 +296,7 @@ export function deployCoreAsync(resp: pxtc.CompileResult) {
.then(() => w.flashAsync(elfPath, UF2.readBytes(origElfUF2, 0, origElfUF2.length * 256))) .then(() => w.flashAsync(elfPath, UF2.readBytes(origElfUF2, 0, origElfUF2.length * 256)))
.then(() => w.flashAsync(rbfPath, rbfBIN)) .then(() => w.flashAsync(rbfPath, rbfBIN))
.then(() => w.runAsync(rbfPath)) .then(() => w.runAsync(rbfPath))
.then(() => pxt.U.delay(500)) .then(() => Promise.delay(500))
.then(() => { .then(() => {
pxt.tickEvent("webserial.success"); pxt.tickEvent("webserial.success");
return w.disconnectAsync() return w.disconnectAsync()

View File

@ -1,5 +1,4 @@
import * as React from "react"; import * as React from "react";
import { canUseWebSerial, enableWebSerialAsync } from "./deploy"; import { canUseWebSerial, enableWebSerialAsync } from "./deploy";
import { projectView } from "./extension"; import { projectView } from "./extension";
@ -22,7 +21,7 @@ export function bluetoothTryAgainAsync(): Promise<void> {
function enableWebSerialAndCompileAsync() { function enableWebSerialAndCompileAsync() {
return enableWebSerialAsync() return enableWebSerialAsync()
.then(() => pxt.U.delay(500)) .then(() => Promise.delay(500))
.then(() => projectView.compile()); .then(() => projectView.compile());
} }
@ -53,12 +52,11 @@ function explainWebSerialPairingAsync(): Promise<void> {
export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (options: any) => Promise<number>): Promise<void> { export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (options: any) => Promise<number>): Promise<void> {
confirmAsync = _confirmAsync; confirmAsync = _confirmAsync;
// https://msdn.microsoft.com/en-us/library/cc848897.aspx // https://msdn.microsoft.com/en-us/library/cc848897.aspx
// "For security reasons, data URIs are restricted to downloaded resources. // "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" // 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 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 = const jsx =
<div className="ui grid stackable"> <div className="ui grid stackable">
@ -120,7 +118,7 @@ export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (o
hideAgree: false, hideAgree: false,
agreeLbl: lf("I got it"), agreeLbl: lf("I got it"),
className: 'downloaddialog', className: 'downloaddialog',
buttons: [canUseWebSerial() && { buttons: [canUseWebSerial() ? {
label: lf("Bluetooth"), label: lf("Bluetooth"),
icon: "bluetooth", icon: "bluetooth",
className: "bluetooth focused", className: "bluetooth focused",
@ -128,19 +126,20 @@ export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (o
pxt.tickEvent("bluetooth.enable"); pxt.tickEvent("bluetooth.enable");
explainWebSerialPairingAsync() explainWebSerialPairingAsync()
.then(() => enableWebSerialAndCompileAsync()) .then(() => enableWebSerialAndCompileAsync())
.done();
} }
}, downloadAgain && { } : undefined, downloadAgain ? {
label: fn, label: fn,
icon: "download", icon: "download",
className: "lightgrey focused", className: "lightgrey focused",
url, url,
fileName: fn fileName: fn
}, docUrl && { } : undefined, docUrl ? {
label: lf("Help"), label: lf("Help"),
icon: "help", icon: "help",
className: "lightgrey", className: "lightgrey",
url: docUrl url: docUrl
}] } : undefined]
//timeout: 20000 //timeout: 20000
}).then(() => { }); }).then(() => { });
} }

View File

@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es2017", "target": "es5",
"noImplicitAny": true, "noImplicitAny": true,
"noImplicitReturns": true, "noImplicitReturns": true,
"noImplicitThis": true, "noImplicitThis": true,

View File

@ -26,7 +26,7 @@ export class Ev3Wrapper {
isStreaming = false; isStreaming = false;
dataDump = /talkdbg=1/.test(window.location.href); dataDump = /talkdbg=1/.test(window.location.href);
constructor(public io: pxt.packetio.PacketIO) { constructor(public io: pxt.HF2.PacketIO) {
io.onData = buf => { io.onData = buf => {
buf = buf.slice(0, HF2.read16(buf, 0) + 2) buf = buf.slice(0, HF2.read16(buf, 0) + 2)
if (HF2.read16(buf, 4) == usbMagic) { if (HF2.read16(buf, 4) == usbMagic) {
@ -81,7 +81,7 @@ export class Ev3Wrapper {
log(`stopping PXT app`) log(`stopping PXT app`)
let buf = this.allocCustom(2) let buf = this.allocCustom(2)
return this.justSendAsync(buf) return this.justSendAsync(buf)
.then(() => pxt.U.delay(500)) .then(() => Promise.delay(500))
}) })
} }
@ -116,7 +116,7 @@ export class Ev3Wrapper {
if (this.dataDump) if (this.dataDump)
log("TALK: " + U.toHex(buf)) log("TALK: " + U.toHex(buf))
return this.io.sendPacketAsync(buf) return this.io.sendPacketAsync(buf)
.then(() => this.msgs.shiftAsync(5000)) .then(() => this.msgs.shiftAsync(1000))
.then(resp => { .then(resp => {
if (resp[2] != buf[2] || resp[3] != buf[3]) if (resp[2] != buf[2] || resp[3] != buf[3])
U.userError("msg count de-sync") U.userError("msg count de-sync")
@ -236,7 +236,7 @@ export class Ev3Wrapper {
let contFileReq = this.allocSystem(1 + 2, 0x97) let contFileReq = this.allocSystem(1 + 2, 0x97)
HF2.write16(contFileReq, 7, 1000) // maxRead HF2.write16(contFileReq, 7, 1000) // maxRead
contFileReq[6] = handle contFileReq[6] = handle
return pxt.U.delay(data.length > 0 ? 0 : 500) return Promise.delay(data.length > 0 ? 0 : 500)
.then(() => this.talkAsync(contFileReq, -1)) .then(() => this.talkAsync(contFileReq, -1))
.then(resp) .then(resp)
} }
@ -251,7 +251,7 @@ export class Ev3Wrapper {
let loop = (): Promise<void> => let loop = (): Promise<void> =>
this.lock.enqueue("file", () => this.lock.enqueue("file", () =>
this.streamFileOnceAsync(path, cb)) this.streamFileOnceAsync(path, cb))
.then(() => pxt.U.delay(500)) .then(() => Promise.delay(500))
.then(loop) .then(loop)
return loop() return loop()
} }

View File

@ -120,17 +120,20 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.
Blockly.DropDownDiv.setColour('#ffffff', '#dddddd'); Blockly.DropDownDiv.setColour('#ffffff', '#dddddd');
// Position based on the field position. // Calculate positioning based on the field position.
Blockly.DropDownDiv.showPositionedByField(this, this.onHide_.bind(this)); let scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
let bBox = { width: this.size_.width, height: this.size_.height };
// Update colour to look selected. bBox.width *= scale;
let source = this.sourceBlock_ as Blockly.BlockSvg; bBox.height *= scale;
this.savedPrimary_ = source?.getColour(); let position = this.fieldGroup_.getBoundingClientRect();
if (source?.isShadow()) { let primaryX = position.left + bBox.width / 2;
source.setColour(source.getColourTertiary()); let primaryY = position.top + bBox.height;
} else if (this.borderRect_) { let secondaryX = primaryX;
this.borderRect_.setAttribute('fill', (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary()); 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-haspopup');
content.removeAttribute('aria-activedescendant'); content.removeAttribute('aria-activedescendant');
(content as HTMLElement).style.width = ''; (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_);
}
}; };
} }

View File

@ -5,14 +5,10 @@ export interface FieldColorEnumOptions extends pxtblockly.FieldColourNumberOptio
} }
export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Blockly.FieldCustom { export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Blockly.FieldCustom {
public isFieldCustom_ = true; public isFieldCustom_ = true;
private paramsData: any[];
constructor(text: string, params: FieldColorEnumOptions, opt_validator?: Function) { constructor(text: string, params: FieldColorEnumOptions, opt_validator?: Function) {
super(text, params, opt_validator); super(text, params, opt_validator);
this.paramsData = params["data"];
} }
mapColour(enumString: string) { mapColour(enumString: string) {
@ -37,21 +33,11 @@ export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Block
case 'ColorSensorColor.Red': return '#f12a21'; case 'ColorSensorColor.Red': return '#f12a21';
case 'ColorSensorColor.White': return '#ffffff'; case 'ColorSensorColor.White': return '#ffffff';
case 'ColorSensorColor.Brown': return '#6c2d00'; case 'ColorSensorColor.Brown': return '#6c2d00';
case 'ColorSensorColor.None': return '#dfe6e9'; case 'ColorSensorColor.None': return '#dfe6e9'; // Grey
default: return colorString; 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. * Return the current colour.
* @param {boolean} opt_asHex optional field if the returned value should be a hex * @param {boolean} opt_asHex optional field if the returned value should be a hex
@ -78,7 +64,7 @@ export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Block
} }
this.value_ = colour; this.value_ = colour;
if (this.sourceBlock_) { if (this.sourceBlock_) {
this.sourceBlock_.setColour(colour); this.sourceBlock_.setColour(colour, colour, colour);
} }
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,6 @@ declare const pxtTargetBundle: any;
let soundCache: any; let soundCache: any;
let soundIconCache: any; let soundIconCache: any;
let soundIconCacheArray: any;
export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldCustom { export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldCustom {
public isFieldCustom_ = true; public isFieldCustom_ = true;
@ -24,17 +23,17 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
super(text, { blocksInfo: options.blocksInfo, sort: true, data: options.data }, validator); super(text, { blocksInfo: options.blocksInfo, sort: true, data: options.data }, validator);
this.columns_ = parseInt(options.columns) || 4; 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.setText = Blockly.FieldDropdown.prototype.setText;
this.updateSize_ = (Blockly.Field as any).prototype.updateSize_; this.updateSize_ = (Blockly.Field as any).prototype.updateSize_;
this.updateTextNode_ = Blockly.Field.prototype.updateTextNode_;
if (!pxt.BrowserUtils.isIE() && !soundCache) { if (!pxt.BrowserUtils.isIE() && !soundCache) {
soundCache = JSON.parse(pxtTargetBundle.bundledpkgs['music']['sounds.jres']); soundCache = JSON.parse(pxtTargetBundle.bundledpkgs['music']['sounds.jres']);
} }
if (!soundIconCache) { if (!soundIconCache) {
soundIconCache = JSON.parse(pxtTargetBundle.bundledpkgs['music']['icons.jres']); soundIconCache = JSON.parse(pxtTargetBundle.bundledpkgs['music']['icons.jres']);
soundIconCacheArray = Object.entries(soundIconCache).filter(el => el[0] !== "*");
} }
} }
@ -51,17 +50,14 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
Blockly.DropDownDiv.hideWithoutAnimation(); Blockly.DropDownDiv.hideWithoutAnimation();
Blockly.DropDownDiv.clearContent(); Blockly.DropDownDiv.clearContent();
// Populate the drop-down with the icons for this field. // 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'); let contentDiv = document.createElement('div');
// Accessibility properties // Accessibility properties
contentDiv.setAttribute('role', 'menu'); contentDiv.setAttribute('role', 'menu');
contentDiv.setAttribute('aria-haspopup', 'true'); contentDiv.setAttribute('aria-haspopup', 'true');
contentDiv.className = 'blocklyMusicFieldOptions'; contentDiv.className = 'blocklyMusicFieldOptions';
contentDiv.style.display = "flex";
contentDiv.style.flexWrap = "wrap";
contentDiv.style.float = "none";
const options = this.getOptions(); const options = this.getOptions();
//options.sort(); // Do not need to use to not apply sorting in different languages options.sort();
// Create categoies // Create categoies
const categories = this.getCategories(options); const categories = this.getCategories(options);
@ -72,7 +68,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
// Accessibility properties // Accessibility properties
categoriesDiv.setAttribute('role', 'menu'); categoriesDiv.setAttribute('role', 'menu');
categoriesDiv.setAttribute('aria-haspopup', 'true'); categoriesDiv.setAttribute('aria-haspopup', 'true');
categoriesDiv.style.backgroundColor = (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary(); categoriesDiv.style.backgroundColor = this.sourceBlock_.getColourTertiary();
categoriesDiv.className = 'blocklyMusicFieldCategories'; categoriesDiv.className = 'blocklyMusicFieldCategories';
this.refreshCategories(categoriesDiv, categories); this.refreshCategories(categoriesDiv, categories);
@ -86,18 +82,30 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
dropdownDiv.appendChild(categoriesDiv); dropdownDiv.appendChild(categoriesDiv);
dropdownDiv.appendChild(contentDiv); dropdownDiv.appendChild(contentDiv);
Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary()); Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), this.sourceBlock_.getColourTertiary());
// Position based on the field position. // Calculate positioning based on the field position.
Blockly.DropDownDiv.showPositionedByField(this, this.onHide_.bind(this)); 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. // Update colour to look selected.
let source = this.sourceBlock_ as Blockly.BlockSvg; if (this.sourceBlock_.isShadow()) {
this.savedPrimary_ = source?.getColour(); this.savedPrimary_ = this.sourceBlock_.getColour();
if (source?.isShadow()) { this.sourceBlock_.setColour(this.sourceBlock_.getColourTertiary(),
source.setColour(source.getColourTertiary()); this.sourceBlock_.getColourSecondary(), this.sourceBlock_.getColourTertiary());
} else if (this.borderRect_) { } else if (this.box_) {
this.borderRect_.setAttribute('fill', (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary()); this.box_.setAttribute('fill', this.sourceBlock_.getColourTertiary());
} }
} }
@ -114,7 +122,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
} }
refreshCategories(categoriesDiv: Element, categories: string[]) { refreshCategories(categoriesDiv: Element, categories: string[]) {
// Show category dropdown. // Show category dropdown.
for (let i = 0; i < categories.length; i++) { for (let i = 0; i < categories.length; i++) {
const category = categories[i]; const category = categories[i];
@ -130,7 +138,6 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
backgroundColor = '#0c4e5e'; backgroundColor = '#0c4e5e';
button.setAttribute('aria-selected', 'true'); button.setAttribute('aria-selected', 'true');
} }
button.style.padding = "2px 6px";
button.style.backgroundColor = backgroundColor; button.style.backgroundColor = backgroundColor;
button.style.borderColor = backgroundColor; button.style.borderColor = backgroundColor;
Blockly.bindEvent_(button, 'click', this, this.categoryClick_); Blockly.bindEvent_(button, 'click', this, this.categoryClick_);
@ -144,7 +151,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
} }
refreshOptions(contentDiv: Element, options: any) { refreshOptions(contentDiv: Element, options: any) {
const categories = this.getCategories(options);
// Show options // Show options
for (let i = 0, option: any; option = options[i]; i++) { for (let i = 0, option: any; option = options[i]; i++) {
let content = (options[i] as any)[0]; // Human-readable text or image. let content = (options[i] as any)[0]; // Human-readable text or image.
@ -179,11 +186,11 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
let backgroundColor = this.savedPrimary_ || this.sourceBlock_.getColour(); let backgroundColor = this.savedPrimary_ || this.sourceBlock_.getColour();
if (value == this.getValue()) { if (value == this.getValue()) {
// This icon is selected, show it in a different colour // This icon is selected, show it in a different colour
backgroundColor = (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary(); backgroundColor = this.sourceBlock_.getColourTertiary();
button.setAttribute('aria-selected', 'true'); button.setAttribute('aria-selected', 'true');
} }
button.style.backgroundColor = backgroundColor; button.style.backgroundColor = backgroundColor;
button.style.borderColor = (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary(); button.style.borderColor = this.sourceBlock_.getColourTertiary();
Blockly.bindEvent_(button, 'click', this, this.buttonClick_); Blockly.bindEvent_(button, 'click', this, this.buttonClick_);
Blockly.bindEvent_(button, 'mouseup', this, this.buttonClick_); Blockly.bindEvent_(button, 'mouseup', this, this.buttonClick_);
// These are applied manually instead of using the :hover pseudoclass // These are applied manually instead of using the :hover pseudoclass
@ -208,27 +215,15 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
this.setAttribute('class', 'blocklyDropDownButton'); this.setAttribute('class', 'blocklyDropDownButton');
contentDiv.removeAttribute('aria-activedescendant'); contentDiv.removeAttribute('aria-activedescendant');
}); });
// Find index in array by category name
const categoryIndex = categories.indexOf(category);
let buttonImg = document.createElement('img'); 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 // 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. // Store a data attribute on all possible click targets so we can match it to the icon.
const textNode = this.createTextNode_(content); const textNode = this.createTextNode_(content);
button.setAttribute('data-value', value); button.setAttribute('data-value', value);
buttonImg.setAttribute('data-value', value); buttonImg.setAttribute('data-value', value);
buttonImg.style.height = "auto";
textNode.setAttribute('data-value', value); 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(buttonImg);
button.appendChild(textNode); button.appendChild(textNode);
@ -243,19 +238,12 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
super.onHide_(); super.onHide_();
(Blockly.DropDownDiv.getContentDiv() as HTMLElement).style.maxHeight = ''; (Blockly.DropDownDiv.getContentDiv() as HTMLElement).style.maxHeight = '';
this.stopSounds(); 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) { protected createTextNode_(content: string) {
const category = this.parseCategory(content); const category = this.parseCategory(content);
let text = content.substr(content.indexOf(' ') + 1); let text = content.substr(content.indexOf(' ') + 1);
text = text.length > 15 ? text.substr(0, 12) + "..." : text;
const textSpan = document.createElement('span'); const textSpan = document.createElement('span');
textSpan.setAttribute('class', 'blocklyDropdownText'); textSpan.setAttribute('class', 'blocklyDropdownText');
textSpan.textContent = text; textSpan.textContent = text;
@ -323,9 +311,9 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
pxsim.AudioContextManager.stop(); pxsim.AudioContextManager.stop();
} }
private getSoundIcon(indexCategory: number) { private getSoundIcon(category: string) {
if (soundIconCacheArray && soundIconCacheArray[indexCategory]) { if (soundIconCache && soundIconCache[category]) {
return soundIconCacheArray[indexCategory][1].icon; return soundIconCache[category].icon;
} }
return undefined; return undefined;
} }

View File

@ -18,6 +18,7 @@ export class FieldPorts extends pxtblockly.FieldImages implements Blockly.FieldC
this.setText = Blockly.FieldDropdown.prototype.setText; this.setText = Blockly.FieldDropdown.prototype.setText;
this.updateSize_ = (Blockly.Field as any).prototype.updateSize_; this.updateSize_ = (Blockly.Field as any).prototype.updateSize_;
this.updateTextNode_ = Blockly.Field.prototype.updateTextNode_;
} }
trimOptions_() { trimOptions_() {

View File

@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es2017", "target": "es5",
"noImplicitAny": false, "noImplicitAny": false,
"noImplicitReturns": true, "noImplicitReturns": true,
"module": "commonjs", "module": "commonjs",

View File

@ -204,8 +204,6 @@ declare namespace control {
*/ */
//% shim=control::dmesgValue //% shim=control::dmesgValue
function dmesgValue(v: any): void; function dmesgValue(v: any): void;
}
declare namespace control {
/** /**
* Force GC and dump basic information about heap. * Force GC and dump basic information about heap.

View File

@ -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 * @param sensor the color sensor port
*/ */
//% help=sensors/color-sensor/light //% help=sensors/color-sensor/light

View File

@ -1,3 +1,5 @@
namespace sensors { namespace sensors {
/** /**
@ -7,9 +9,9 @@ namespace sensors {
//% blockId=colorEnumPicker block="%color" shim=TD_ID //% blockId=colorEnumPicker block="%color" shim=TD_ID
//% weight=0 blockHidden=1 turnRatio.fieldOptions.decompileLiterals=1 //% weight=0 blockHidden=1 turnRatio.fieldOptions.decompileLiterals=1
//% color.fieldEditor="colorenum" //% 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' //% color.fieldOptions.columns=2 color.fieldOptions.className='legoColorPicker'
export function __colorEnumPicker(color: ColorSensorColor): number { export function __colorEnumPicker(color: ColorSensorColor): number {
return color; return color;
} }
} }

View File

@ -1,11 +0,0 @@
namespace control {
let lastPause = 0;
const COOPERATION_INTERVAL = 20
export function cooperate() {
const now = control.millis()
if (now - lastPause > COOPERATION_INTERVAL) {
lastPause = now
pause(1)
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -21,7 +21,8 @@ namespace sensors.internal {
const now = control.millis(); const now = control.millis();
if (now - this.lastQuery >= this.interval * 2) if (now - this.lastQuery >= this.interval * 2)
this.queryAndUpdate(); // sensor poller is not allowed to run this.queryAndUpdate(); // sensor poller is not allowed to run
control.cooperate(); // allow events to trigger if (now - this.lastPause >= this.interval * 5)
pause(1); // allow events to trigger
} }
private queryAndUpdate() { private queryAndUpdate() {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -124,7 +124,7 @@ namespace motors {
export function stopAll() { export function stopAll() {
const b = mkCmd(Output.ALL, DAL.opOutputStop, 0) const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
writePWM(b); writePWM(b);
control.cooperate(); pause(1);
} }
/** /**
@ -136,7 +136,7 @@ namespace motors {
//% help=motors/reset-all //% help=motors/reset-all
export function resetAll() { export function resetAll() {
reset(Output.ALL) reset(Output.ALL)
control.cooperate(); pause(1);
} }
interface MoveSchedule { interface MoveSchedule {
@ -196,7 +196,6 @@ namespace motors {
*/ */
//% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake=toggleOnOff" //% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake=toggleOnOff"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=60 blockGap=8 //% weight=60 blockGap=8
//% group="Properties" //% group="Properties"
//% help=motors/motor/set-brake //% help=motors/motor/set-brake
@ -211,7 +210,6 @@ namespace motors {
*/ */
//% blockId=outputMotorSetPauseMode block="set %motor|pause on run %brake=toggleOnOff" //% blockId=outputMotorSetPauseMode block="set %motor|pause on run %brake=toggleOnOff"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=60 blockGap=8 //% weight=60 blockGap=8
//% group="Properties" //% group="Properties"
setPauseOnRun(value: boolean) { setPauseOnRun(value: boolean) {
@ -219,12 +217,11 @@ namespace motors {
this._pauseOnRun = value; this._pauseOnRun = value;
} }
/** /**
* Inverts the motor polarity * Inverts the motor polarity
*/ */
//% blockId=motorSetInverted block="set %motor|inverted %reversed=toggleOnOff" //% blockId=motorSetInverted block="set %motor|inverted %reversed=toggleOnOff"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=59 blockGap=8 //% weight=59 blockGap=8
//% group="Properties" //% group="Properties"
//% help=motors/motor/set-inverted //% help=motors/motor/set-inverted
@ -237,12 +234,11 @@ namespace motors {
return this._inverted ? -1 : 1; return this._inverted ? -1 : 1;
} }
/** /**
* Set the settle time after braking in milliseconds (default is 10ms). * Set the settle time after braking in milliseconds (default is 10ms).
*/ */
//% blockId=motorSetBrakeSettleTime block="set %motor|brake settle time %millis|ms" //% blockId=motorSetBrakeSettleTime block="set %motor|brake settle time %millis|ms"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=1 blockGap=8 //% weight=1 blockGap=8
//% group="Properties" //% group="Properties"
//% millis.defl=200 millis.min=0 millis.max=500 //% millis.defl=200 millis.min=0 millis.max=500
@ -273,7 +269,7 @@ namespace motors {
if (this._brake && this._brakeSettleTime > 0) if (this._brake && this._brakeSettleTime > 0)
pause(this._brakeSettleTime); pause(this._brakeSettleTime);
else { else {
control.cooperate(); pause(1);
} }
} }
@ -284,7 +280,7 @@ namespace motors {
// allow robot to settle // allow robot to settle
this.settle(); this.settle();
} else { } else {
control.cooperate(); pause(1);
} }
} }
@ -348,7 +344,6 @@ namespace motors {
//% weight=100 blockGap=8 //% weight=100 blockGap=8
//% group="Move" //% group="Move"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% expandableArgumentMode=toggle //% expandableArgumentMode=toggle
//% help=motors/motor/run //% help=motors/motor/run
run(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) { run(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
@ -362,7 +357,7 @@ namespace motors {
// special: 0 is infinity // special: 0 is infinity
if (schedule.steps[0] + schedule.steps[1] + schedule.steps[2] == 0) { if (schedule.steps[0] + schedule.steps[1] + schedule.steps[2] == 0) {
this._run(schedule.speed); this._run(schedule.speed);
control.cooperate(); pause(1);
return; return;
} }
@ -398,7 +393,6 @@ namespace motors {
//% weight=99 blockGap=8 //% weight=99 blockGap=8
//% group="Move" //% group="Move"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% help=motors/motor/ramp //% help=motors/motor/ramp
//% inlineInputMode=inline //% inlineInputMode=inline
//% expandableArgumentMode=toggle //% expandableArgumentMode=toggle
@ -428,7 +422,6 @@ namespace motors {
*/ */
//% blockId=outputMotorsetRunRamp block="set %motor|run %ramp to $value||$unit" //% blockId=outputMotorsetRunRamp block="set %motor|run %ramp to $value||$unit"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=21 blockGap=8 //% weight=21 blockGap=8
//% group="Properties" //% group="Properties"
//% help=motors/motor/set-run-phase //% help=motors/motor/set-run-phase
@ -500,7 +493,6 @@ namespace motors {
*/ */
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff" //% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=58 blockGap=8 //% weight=58 blockGap=8
//% group="Properties" //% group="Properties"
//% help=motors/motor/set-regulated //% help=motors/motor/set-regulated
@ -526,7 +518,6 @@ namespace motors {
*/ */
//% blockId=motorPauseUntilRead block="pause until %motor|ready" //% blockId=motorPauseUntilRead block="pause until %motor|ready"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=90 blockGap=8 //% weight=90 blockGap=8
//% group="Move" //% group="Move"
pauseUntilReady(timeOut?: number) { pauseUntilReady(timeOut?: number) {
@ -585,8 +576,7 @@ namespace motors {
*/ */
//% blockId=motorSpeed block="%motor|speed" //% blockId=motorSpeed block="%motor|speed"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1 //% weight=72
//% weight=72
//% blockGap=8 //% blockGap=8
//% group="Counters" //% group="Counters"
//% help=motors/motor/speed //% help=motors/motor/speed
@ -601,14 +591,13 @@ namespace motors {
*/ */
//% blockId=motorAngle block="%motor|angle" //% blockId=motorAngle block="%motor|angle"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=70 //% weight=70
//% blockGap=8 //% blockGap=8
//% group="Counters" //% group="Counters"
//% help=motors/motor/angle //% help=motors/motor/angle
angle(): number { angle(): number {
this.init(); this.init();
return getMotorData(this._port).count * this.invertedFactor(); return getMotorData(this._port).count;
} }
/** /**
@ -616,7 +605,6 @@ namespace motors {
*/ */
//% blockId=motorClearCount block="clear %motor|counters" //% blockId=motorClearCount block="clear %motor|counters"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=68 //% weight=68
//% blockGap=8 //% blockGap=8
//% group="Counters" //% group="Counters"
@ -645,7 +633,6 @@ namespace motors {
*/ */
//% blockId=motorPauseUntilStall block="pause until %motor|stalled" //% blockId=motorPauseUntilStall block="pause until %motor|stalled"
//% motor.fieldEditor="motors" //% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=89 //% weight=89
//% group="Move" //% group="Move"
//% help=motors/motor/pause-until-stalled //% help=motors/motor/pause-until-stalled
@ -669,28 +656,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); 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); 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); 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); 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); 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); 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); 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); export const mediumD = new Motor(Output.D, false);
//% fixedInstances //% fixedInstances
@ -710,10 +697,10 @@ namespace motors {
} }
/** /**
* The Move Tank block can make a robot drive forward, backward, turn, or stop. * The Move Tank block can make a robot drive forward, backward, turn, or stop.
* Use the Move Tank block for robot vehicles that have two Large Motors, * Use the Move Tank block for robot vehicles that have two Large Motors,
* with one motor driving the left side of the vehicle and the other the right side. * with one motor driving the left side of the vehicle and the other the right side.
* You can make the two motors go at different speeds or in different directions * You can make the two motors go at different speeds or in different directions
* to make your robot turn. * to make your robot turn.
* @param speedLeft the speed on the left motor, eg: 50 * @param speedLeft the speed on the left motor, eg: 50
* @param speedRight the speed on the right motor, eg: 50 * @param speedRight the speed on the right motor, eg: 50
@ -721,7 +708,7 @@ namespace motors {
* @param unit (optional) unit of the value * @param unit (optional) unit of the value
*/ */
//% blockId=motorPairTank block="tank **motors** %motors %speedLeft=motorSpeedPicker|\\% %speedRight=motorSpeedPicker|\\%||for %value %unit" //% blockId=motorPairTank block="tank **motors** %motors %speedLeft=motorSpeedPicker|\\% %speedRight=motorSpeedPicker|\\%||for %value %unit"
//% motors.fieldEditor="motors" //% motors.fieldEditor="ports"
//% weight=96 blockGap=8 //% weight=96 blockGap=8
//% inlineInputMode=inline //% inlineInputMode=inline
//% group="Move" //% group="Move"
@ -751,7 +738,7 @@ namespace motors {
* @param unit (optional) unit of the value * @param unit (optional) unit of the value
*/ */
//% blockId=motorPairSteer block="steer **motors** %chassis turn ratio %turnRatio=motorTurnRatioPicker speed %speed=motorSpeedPicker|\\%||for %value %unit" //% blockId=motorPairSteer block="steer **motors** %chassis turn ratio %turnRatio=motorTurnRatioPicker speed %speed=motorSpeedPicker|\\%||for %value %unit"
//% chassis.fieldEditor="motors" //% chassis.fieldEditor="ports"
//% weight=95 //% weight=95
//% turnRatio.min=-200 turnRatio=200 //% turnRatio.min=-200 turnRatio=200
//% inlineInputMode=inline //% inlineInputMode=inline
@ -824,16 +811,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); 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); 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); 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); export const largeCD = new SynchedMotorPair(Output.CD);
function reset(out: Output) { function reset(out: Output) {

View File

@ -28,8 +28,7 @@
"platform.h", "platform.h",
"platform.cpp", "platform.cpp",
"dmesg.cpp", "dmesg.cpp",
"integrator.ts", "integrator.ts"
"cooperate.ts"
], ],
"testFiles": [ "testFiles": [
"test.ts" "test.ts"

View File

@ -12,5 +12,4 @@ music.setTempo(120)
music.noteFrequency(Note.C) music.noteFrequency(Note.C)
music.beat() music.beat()
music.setVolume(50) music.setVolume(50)
music.volume() ```
```

View File

@ -13,22 +13,7 @@
namespace music { namespace music {
int _readSystemVolume() { uint8_t currVolume = 50;
char ParBuf[8];
int volume;
int fd = open("../sys/settings/Volume.rtf", O_RDONLY);
read(fd, ParBuf, sizeof(ParBuf));
close(fd);
if (sscanf(ParBuf,"%d",&volume) > 0) {
if ((volume >= 0) && (volume <= 100)) {
return volume;
}
}
return 50;
}
uint8_t currVolume = _readSystemVolume();
uint8_t *lmsSoundMMap; uint8_t *lmsSoundMMap;
int writeDev(void *data, int size) { int writeDev(void *data, int size) {
@ -52,18 +37,6 @@ void setVolume(int volume) {
currVolume = max(0, min(100, volume)); currVolume = max(0, min(100, volume));
} }
/**
* Return the output volume of the sound synthesizer.
*/
//% weight=96
//% blockId=synth_get_volume block="volume"
//% parts="speaker" blockGap=8
//% help=music/volume
//% weight=1
int volume() {
return currVolume;
}
#define SOUND_CMD_BREAK 0 #define SOUND_CMD_BREAK 0
#define SOUND_CMD_TONE 1 #define SOUND_CMD_TONE 1
#define SOUND_CMD_PLAY 2 #define SOUND_CMD_PLAY 2
@ -72,7 +45,7 @@ int volume() {
struct ToneCmd { struct ToneCmd {
uint8_t cmd; uint8_t cmd;
uint8_t lvl; uint8_t vol;
uint16_t freq; uint16_t freq;
uint16_t duration; uint16_t duration;
}; };
@ -82,26 +55,10 @@ static void _stopSound() {
writeDev(&cmd, sizeof(cmd)); writeDev(&cmd, sizeof(cmd));
} }
static uint8_t _getVolumeLevel(uint8_t volume, uint8_t levels) {
uint8_t level;
uint8_t step = (uint8_t) (100 / (levels - 1));
if (volume < step) {
level = 0;
} else if (volume > step * (levels - 1)) {
level = levels;
} else {
level = (uint8_t) (volume / step);
}
return level;
}
static void _playTone(uint16_t frequency, uint16_t duration, uint8_t volume) { static void _playTone(uint16_t frequency, uint16_t duration, uint8_t volume) {
// https://github.com/mindboards/ev3sources/blob/78ebaf5b6f8fe31cc17aa5dce0f8e4916a4fc072/lms2012/c_sound/source/c_sound.c#L471
uint8_t level = _getVolumeLevel(volume, 13);
ToneCmd cmd; ToneCmd cmd;
cmd.cmd = SOUND_CMD_TONE; cmd.cmd = SOUND_CMD_TONE;
cmd.lvl = level; cmd.vol = volume;
cmd.freq = frequency; cmd.freq = frequency;
cmd.duration = duration; cmd.duration = duration;
// (*SoundInstance.pSound).Busy = TRUE; // (*SoundInstance.pSound).Busy = TRUE;
@ -165,8 +122,7 @@ void playSample(Buffer buf) {
stopUser(); stopUser();
pthread_mutex_lock(&pumpMutex); pthread_mutex_lock(&pumpMutex);
*lmsSoundMMap = 1; // BUSY *lmsSoundMMap = 1; // BUSY
// https://github.com/mindboards/ev3sources/blob/78ebaf5b6f8fe31cc17aa5dce0f8e4916a4fc072/lms2012/c_sound/source/c_sound.c#L605 uint8_t cmd[] = {SOUND_CMD_PLAY, (uint8_t)((currVolume / 33) + 1)};
uint8_t cmd[] = {SOUND_CMD_PLAY, _getVolumeLevel(currVolume, 8)};
writeDev(cmd, 2); writeDev(cmd, 2);
decrRC(currentSample); decrRC(currentSample);
currentSample = buf; currentSample = buf;
@ -245,4 +201,4 @@ Buffer buffer(Sound snd) {
void play(Sound snd) { void play(Sound snd) {
music::playSample(snd); music::playSample(snd);
} }
} }

10
libs/music/shims.d.ts vendored
View File

@ -13,16 +13,6 @@ declare namespace music {
//% weight=1 shim=music::setVolume //% weight=1 shim=music::setVolume
function setVolume(volume: int32): void; function setVolume(volume: int32): void;
/**
* Return the output volume of the sound synthesizer.
*/
//% weight=96
//% blockId=synth_get_volume block="volume"
//% parts="speaker" blockGap=8
//% help=music/volume
//% weight=1 shim=music::volume
function volume(): int32;
/** /**
* Play a tone through the speaker for some amount of time. * Play a tone through the speaker for some amount of time.
* @param frequency pitch of the tone to play in Hertz (Hz), eg: Note.C * @param frequency pitch of the tone to play in Hertz (Hz), eg: Note.C

View File

@ -5,4 +5,3 @@ music.playTone(1440, 500)
pause(500) pause(500)
music.playTone(2440, 500) music.playTone(2440, 500)
pause(500) pause(500)
music.volume()

View File

@ -22,7 +22,6 @@ namespace _screen_internal {
namespace brick { namespace brick {
const textOffset = 4; const textOffset = 4;
const lineOffset = 2; const lineOffset = 2;
enum ScreenMode { enum ScreenMode {
None, None,
ShowLines, ShowLines,
@ -30,14 +29,6 @@ namespace brick {
Ports, Ports,
Custom Custom
} }
export enum PrintStyle {
//% block="black on white"
BlackOnWhite,
//% block="white on black"
WhiteOnBlack
}
let screenMode = ScreenMode.None; let screenMode = ScreenMode.None;
export let font = image.font8; export let font = image.font8;
@ -57,48 +48,6 @@ namespace brick {
return ((screen.height - textOffset) / lineHeight()) >> 0 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. * Show text on the screen at a specific line.
* @param text the text to print on the screen, eg: "Hello world" * @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" //% blockId=screen_print block="show string %text|at line %line"
//% weight=98 group="Screen" inlineInputMode="inline" blockGap=8 //% weight=98 group="Screen" inlineInputMode="inline" blockGap=8
//% help=brick/show-string //% help=brick/show-string
//% line.min=1 line.max=12 //% line.min=1 line.max=10
//% deprecated=true
export function showString(text: string, line: number) { export function showString(text: string, line: number) {
if (screenMode != ScreenMode.ShowLines) { if (screenMode != ScreenMode.ShowLines) {
screenMode = ScreenMode.ShowLines; screenMode = ScreenMode.ShowLines;
@ -126,56 +74,19 @@ namespace brick {
screen.print(text, textOffset, y, 1, font); 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 * Show a number on the screen
* @param value the numeric value * @param value the numeric value
* @param line the line number to print the text at, eg: 1 * @param line the line number to print the text at, eg: 1
*/ */
//% blockId=screenShowNumber block="show number %name|at line %line" //% 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 //% help=brick/show-number
//% line.min=1 line.max=12 //% line.min=1 line.max=10
//% deprecated=true
export function showNumber(value: number, line: number) { export function showNumber(value: number, line: number) {
showString("" + value, line); 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 * Show a name, value pair on the screen
* @param value the numeric value * @param value the numeric value
@ -184,8 +95,7 @@ namespace brick {
//% blockId=screenShowValue block="show value %name|= %text|at line %line" //% blockId=screenShowValue block="show value %name|= %text|at line %line"
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8 //% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
//% help=brick/show-value //% help=brick/show-value
//% line.min=1 line.max=12 //% line.min=1 line.max=10
//% deprecated=true
export function showValue(name: string, value: number, line: number) { export function showValue(name: string, value: number, line: number) {
value = Math.round(value * 1000) / 1000; value = Math.round(value * 1000) / 1000;
showString((name ? name + ": " : "") + value, line); showString((name ? name + ": " : "") + value, line);
@ -213,11 +123,11 @@ namespace brick {
*/ */
//% blockId=brickShowPorts block="show ports" //% blockId=brickShowPorts block="show ports"
//% help=brick/show-ports blockGap=8 //% help=brick/show-ports blockGap=8
//% weight=95 group="Screen" //% weight=10 group="Screen"
export function showPorts() { export function showPorts() {
if (screenMode == ScreenMode.Ports) return; if (screenMode == ScreenMode.Ports) return;
screenMode = ScreenMode.Ports;
screenMode = ScreenMode.Ports;
renderPorts(); renderPorts();
control.runInParallel(function () { control.runInParallel(function () {
while (screenMode == ScreenMode.Ports) { while (screenMode == ScreenMode.Ports) {
@ -236,14 +146,11 @@ namespace brick {
for (let i = 0; i < 4; ++i) { for (let i = 0; i < 4; ++i) {
const x = i * col + 2; const x = i * col + 2;
if (screenMode != ScreenMode.Ports) return; screen.print("ABCD"[i], x, 1 * 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)
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, 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) { function scale(x: number) {
if (Math.abs(x) >= 5000) { if (Math.abs(x) >= 5000) {
@ -260,9 +167,8 @@ namespace brick {
const data = datas[i]; const data = datas[i];
const x = i * col + 2; const x = i * col + 2;
if (!data.actualSpeed && !data.count) continue; 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.actualSpeed)}%`, x, 3 * lineHeight8, 1, image.font8); screen.print(`${scale(data.count)}>`, x, 4 * lineHeight8, 1, image.font8)
screen.print(`${scale(data.count)}>`, x, 4 * lineHeight8, 1, image.font8);
} }
// sensors // sensors
@ -271,16 +177,16 @@ namespace brick {
const si = sis[i]; const si = sis[i];
const x = (si.port() - 1) * col + 2; const x = (si.port() - 1) * col + 2;
const inf = si._info(); const inf = si._info();
if (screenMode != ScreenMode.Ports) return; if (inf)
if (inf) screen.print(inf, x, h - 2 * lineHeight8, 1, inf.length > 4 ? image.font5 : image.font8); screen.print(inf, x, h - 2 * lineHeight8, 1, inf.length > 4 ? image.font5 : image.font8);
} }
} }
export function showBoot() { export function showBoot() {
// pulse green, play startup sound, turn off light // pulse green, play startup sound, turn off light
brick.setStatusLight(StatusLight.GreenPulse); brick.setStatusLight(StatusLight.GreenPulse);
// We pause to give time to read sensor values, so they work in on_start block // We pause for 100ms 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 pause(400)
// and we're ready // and we're ready
brick.setStatusLight(StatusLight.Off); brick.setStatusLight(StatusLight.Off);
// always show port by default if no UI is set // always show port by default if no UI is set
@ -304,33 +210,11 @@ namespace brick {
return image; 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 * Clear the screen
*/ */
//% blockId=screen_clear_screen block="clear screen" //% blockId=screen_clear_screen block="clear screen"
//% weight=93 group="Screen" //% weight=90 group="Screen"
//% help=brick/clear-screen weight=1 //% help=brick/clear-screen weight=1
export function clearScreen() { export function clearScreen() {
screen.fill(0) screen.fill(0)

View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "1.4.32", "version": "1.4.21",
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode", "description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
"private": false, "private": false,
"keywords": [ "keywords": [
@ -32,20 +32,21 @@
"docs/*/*/*.md" "docs/*/*/*.md"
], ],
"devDependencies": { "devDependencies": {
"@types/marked": "^0.3.0", "react": "16.8.3",
"@types/node": "^9.3.0", "webfonts-generator": "^0.4.0",
"@types/react": "16.8.25", "@types/jquery": "3.2.16",
"@types/react": "16.0.25",
"@types/react-dom": "16.0.3", "@types/react-dom": "16.0.3",
"@types/web-bluetooth": "0.0.4", "@types/web-bluetooth": "0.0.4",
"@vusion/webfonts-generator": "^0.7.1", "@types/bluebird": "^2.0.33",
"react": "16.8.3", "@types/marked": "^0.3.0",
"react-dom": "16.11.0", "@types/node": "^9.3.0",
"semantic-ui-less": "2.4.1", "semantic-ui-less": "2.2.14",
"typescript": "^4.2.3" "typescript": "^3.7.5"
}, },
"dependencies": { "dependencies": {
"pxt-common-packages": "9.2.7", "pxt-common-packages": "8.1.3",
"pxt-core": "7.2.27" "pxt-core": "6.2.8"
}, },
"scripts": { "scripts": {
"test": "node node_modules/pxt-core/built/pxt.js travis" "test": "node node_modules/pxt-core/built/pxt.js travis"

View File

@ -77,9 +77,8 @@
"pauseUntilBlock": { "pauseUntilBlock": {
"category": "loops" "category": "loops"
}, },
"breakBlock": true, "bannedCategories": [
"continueBlock": true, ]
"bannedCategories": []
}, },
"compileService": { "compileService": {
"buildEngine": "dockermake", "buildEngine": "dockermake",
@ -107,21 +106,20 @@
"driveDisplayName": "EV3", "driveDisplayName": "EV3",
"boardName": "LEGO® MINDSTORMS® Education 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.", "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, "selectLanguage": true,
"blocksCollapsing": true,
"highContrast": true,
"greenScreen": true, "greenScreen": true,
"availableLocales": [ "availableLocales": [
"en", "en",
"de", "de",
"ja", "ja",
"ru", "ru",
"zh-CN", "zh-CN"
"fr"
], ],
"highContrast": true,
"lightToc": true, "lightToc": true,
"docMenu": [{ "docMenu": [
{
"name": "Support", "name": "Support",
"path": "https://forum.makecode.com/" "path": "https://forum.makecode.com/"
}, },
@ -160,10 +158,7 @@
"extendEditor": true, "extendEditor": true,
"extendFieldEditors": true, "extendFieldEditors": true,
"scriptManager": true, "scriptManager": true,
"debugger": true,
"errorList": true,
"importExtensionFiles": true, "importExtensionFiles": true,
"addNewTypeScriptFile": true,
"experiments": [ "experiments": [
"python", "python",
"alwaysGithubItemBlocks" "alwaysGithubItemBlocks"
@ -211,4 +206,4 @@
}, },
"ignoreDocsErrors": true, "ignoreDocsErrors": true,
"uploadDocs": true "uploadDocs": true
} }

View File

@ -1,6 +1,7 @@
CACHE MANIFEST CACHE MANIFEST
CACHE: CACHE:
/cdn/bluebird.min.js
/cdn/pxtsim.js /cdn/pxtsim.js
/sim/common-sim.js /sim/common-sim.js
/sim/sim.js /sim/sim.js

View File

@ -23,6 +23,7 @@ body {
transition: none !important; transition: none !important;
} }
</style> </style>
<script src="/cdn/bluebird.min.js"></script>
<script src="/cdn/pxtsim.js"></script> <script src="/cdn/pxtsim.js"></script>
<script src="/sim/common-sim.js"></script> <script src="/sim/common-sim.js"></script>
<script src="/sim/sim.js"></script> <script src="/sim/sim.js"></script>

View File

@ -21,7 +21,7 @@ namespace pxsim {
export class ColorSensorNode extends UartSensorNode { export class ColorSensorNode extends UartSensorNode {
id = NodeType.ColorSensor; id = NodeType.ColorSensor;
private color: number = 0; private color: number = 50;
constructor(port: number) { constructor(port: number) {
super(port); super(port);
@ -40,13 +40,5 @@ namespace pxsim {
getValue() { getValue() {
return this.color; 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;
}
} }
} }

View File

@ -37,7 +37,7 @@ namespace pxsim {
return Math.round(this.angle); return Math.round(this.angle);
} }
// returns the secondary motor if any // returns the slave motor if any
getSynchedMotor() { getSynchedMotor() {
return this._synchedMotor; return this._synchedMotor;
} }

View File

@ -7,14 +7,6 @@ namespace pxsim.music {
export function stopAllSounds() { export function stopAllSounds() {
SoundMethods.stop() SoundMethods.stop()
} }
pxsim.music.setVolume = (volume: number): void => {
pxsim.getAudioState().volume = volume;
};
export function volume() {
return pxsim.getAudioState().volume;
}
} }
namespace pxsim.SoundMethods { namespace pxsim.SoundMethods {

View File

@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "es2017", "target": "es5",
"noImplicitAny": true, "noImplicitAny": true,
"noImplicitReturns": true, "noImplicitReturns": true,
"declaration": true, "declaration": true,
@ -8,8 +8,8 @@
"rootDir": ".", "rootDir": ".",
"newLine": "LF", "newLine": "LF",
"sourceMap": false, "sourceMap": false,
"lib": ["dom", "dom.iterable", "scripthost", "es2017"], "lib": ["dom", "dom.iterable", "scripthost", "es6"],
"types": [], "types": ["bluebird"],
"typeRoots": ["../node_modules/@types"] "typeRoots": ["../node_modules/@types"]
} }
} }

View File

@ -19,7 +19,7 @@ namespace pxsim.visuals {
-webkit-user-select: none; -webkit-user-select: none;
-moz-user-select: none; -moz-user-select: none;
-ms-user-select: none; -ms-user-select: none;
user-select: none; user-select: none;
} }
.sim-button { .sim-button {
cursor: pointer; cursor: pointer;
@ -241,8 +241,6 @@ namespace pxsim.visuals {
view = new ColorGridControl(this.element, this.defs, state, port); view = new ColorGridControl(this.element, this.defs, state, port);
} else if (state.getMode() == ColorSensorMode.Reflected) { } else if (state.getMode() == ColorSensorMode.Reflected) {
view = new ColorWheelControl(this.element, this.defs, state, port); 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) { } else if (state.getMode() == ColorSensorMode.Ambient) {
view = new ColorWheelControl(this.element, this.defs, state, port); view = new ColorWheelControl(this.element, this.defs, state, port);
} }
@ -383,7 +381,7 @@ namespace pxsim.visuals {
this.screenCanvas = document.createElement("canvas"); this.screenCanvas = document.createElement("canvas");
this.screenCanvas.id = "board-screen-canvas"; this.screenCanvas.id = "board-screen-canvas";
this.screenCanvas.style.userSelect = "none"; this.screenCanvas.style.userSelect = "none";
(this.screenCanvas.style as any).msUserSelect = "none"; this.screenCanvas.style.msUserSelect = "none";
this.screenCanvas.style.webkitUserSelect = "none"; this.screenCanvas.style.webkitUserSelect = "none";
(this.screenCanvas.style as any).MozUserSelect = "none"; (this.screenCanvas.style as any).MozUserSelect = "none";
this.screenCanvas.style.position = "absolute"; this.screenCanvas.style.position = "absolute";

View File

@ -5,8 +5,8 @@ namespace pxsim.visuals {
export class ColorGridControl extends ControlView<ColorSensorNode> { export class ColorGridControl extends ControlView<ColorSensorNode> {
private group: SVGGElement; private group: SVGGElement;
private static colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'brown', 'white', 'none']; private static colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey', 'white'];
private static colorValue = [5, 4, 2, 3, 1, 7, 6, 0]; private static colorValue = [5, 4, 2, 3, 1, 7, 6];
private colorDivs: Element[] = []; private colorDivs: Element[] = [];
@ -15,7 +15,7 @@ namespace pxsim.visuals {
this.group.setAttribute("transform", `translate(2, 2.5) scale(0.6)`) this.group.setAttribute("transform", `translate(2, 2.5) scale(0.6)`)
const colors = ['#f12a21', '#ffd01b', '#006db3', '#00934b', '#000', '#6c2d00']; 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; let cy = -4;
for (let c = 0; c < colorIds.length; c++) { 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 whiteCircleWrapper = pxsim.svg.child(this.group, "g", { 'id': 'white-cirlce-wrapper' });
const noneCircleWrapper = pxsim.svg.child(this.group, "g", { 'id': 'nothing-circle-wrapper' }); 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` });
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` }); this.colorDivs.push(circle);
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%;` }); pxsim.svg.child(whiteCircleWrapper, "circle", { 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: none;stroke: #94989b;stroke-width: 0.1px` });
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` });
pointerEvents.down.forEach(evid => whiteCircleWrapper.addEventListener(evid, ev => { pointerEvents.down.forEach(evid => whiteCircleWrapper.addEventListener(evid, ev => {
this.setColor(6); this.setColor(6);
})); }));
pointerEvents.down.forEach(evid => noneCircleWrapper.addEventListener(evid, ev => {
this.setColor(0);
}));
return this.group; return this.group;
} }

View File

@ -26,12 +26,8 @@ namespace pxsim.visuals {
return 131; return 131;
} }
private getMaxValue(state: ColorSensorMode) { private getMaxValue() {
return (state == ColorSensorMode.RefRaw ? 1023 : 100); return 100;
}
private mapValue(x: number, inMin: number, inMax: number, outMin: number, outMax: number) {
return (x - inMin) * (outMax - outMin) / (inMax - inMin) + outMin;
} }
updateState() { updateState() {
@ -39,12 +35,10 @@ namespace pxsim.visuals {
return; return;
} }
const node = this.state; const node = this.state;
const value = node.getValue(); const percentage = node.getValue();
let inverseValue = this.getMaxValue(node.getMode()) - value; const inversePercentage = this.getMaxValue() - percentage;
if (node.getMode() == ColorSensorMode.RefRaw) inverseValue = this.mapValue(inverseValue, 0, 1023, 0, 100); svg.setGradientValue(this.colorGradient, inversePercentage + "%");
svg.setGradientValue(this.colorGradient, inverseValue + "%"); this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}%`;
this.reporter.textContent = `${parseFloat((value).toString()).toFixed(0)}`;
if (node.getMode() != ColorSensorMode.RefRaw) this.reporter.textContent += `%`;
} }
updateColorLevel(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) { updateColorLevel(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
@ -53,7 +47,7 @@ namespace pxsim.visuals {
const height = bBox.height; const height = bBox.height;
let t = Math.max(0, Math.min(1, (height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height)); let t = Math.max(0, Math.min(1, (height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height));
const state = this.state; const state = this.state;
state.setColor(t * this.getMaxValue(state.getMode())); state.setColor(t * this.getMaxValue());
} }
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) { getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {

View File

@ -29,7 +29,6 @@ namespace pxsim.visuals {
switch (mode) { switch (mode) {
case ColorSensorMode.Colors: this.updateSensorLightVisual('#0062DD'); return; // blue case ColorSensorMode.Colors: this.updateSensorLightVisual('#0062DD'); return; // blue
case ColorSensorMode.Reflected: this.updateSensorLightVisual('#F86262'); return; // red 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 case ColorSensorMode.Ambient: this.updateSensorLightVisual('#67C3E2'); return; // light blue
} }
this.updateSensorLightVisual('#ffffff'); this.updateSensorLightVisual('#ffffff');

View File

@ -92,11 +92,6 @@
color: white; color: white;
} }
/* active toggle */
.ui.item.editor-menuitem .active~.item.toggle {
background: @editorToggleColor!important;
}
.menubar .ui.item.editor-menuitem .item.toggle { .menubar .ui.item.editor-menuitem .item.toggle {
height: 45px; height: 45px;
} }

View File

@ -17,8 +17,6 @@
specify theme name below specify theme name below
*/ */
@placeholder: 'default';
/* Global */ /* Global */
@site : 'pxt'; @site : 'pxt';
@reset : 'default'; @reset : 'default';
@ -89,7 +87,7 @@
Import Theme Import Theme
*******************************/ *******************************/
@import (multiple) "theme.less"; @import "theme.less";
@fontPath : 'fonts'; @fontPath : 'fonts';