Compare commits

...

41 Commits

Author SHA1 Message Date
Dmitriy Antipov
6d222c50cb
Enable some features to improve the programming experience (#1022)
* Update pxtarget.json

Enable addNewTypeScriptFile so that you can split your code into multiple files. Enable blocksCollapsing to collapse blocks for convenience. Turn off highContrast it doesn't work now. We'll see later...

* enable-errorlist-option

* Update pxtarget.json

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>

---------

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>
2023-05-18 10:24:11 -07:00
Dmitriy Antipov
af263c8183
change-gray-ti-brown (#1021)
A typo that hadn't been noticed before. Does not affect the operation of the simulator.
2023-05-06 09:47:27 -07:00
Joey Wunderlich
dd18007035 1.4.32 2023-05-05 16:18:41 -07:00
Dmitriy Antipov
fba924d125
Add a none option to the simulator for the color sensor and colorEnumPicker extension (#1018)
* Update colorGrid.ts

* Update ns.ts

Added option to select emptiness (nothing) for the colorEnumPicker block.

* set-new-names-for-color-cells

Set new names for colored cells that pops up when hovering over an element. So the user will understand the color.

* Update sim/visuals/controls/colorGrid.ts

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>

---------

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>
2023-05-05 16:04:13 -07:00
Dmitriy Antipov
76257775c3
Extended show screen blocks options (#1019)
* Update targetoverrides.ts

Convert old blocks to obsolete ones, new blocks differ in that you can specify the place to start printing along the horizontal axis of the screen (column). And also added a print style. These are the standard black text on a white background and the new white text on a black background. These two parameters are optionally expanded and optional, by default column = 1 and the print style is the same as before, black text on white.

* Update targetoverrides.ts

* Update libs/screen/targetoverrides.ts

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>

* Update libs/screen/targetoverrides.ts

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>

* Update libs/screen/targetoverrides.ts

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>

* Update libs/screen/targetoverrides.ts

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>

* Update libs/screen/targetoverrides.ts

---------

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>
2023-05-05 15:58:52 -07:00
Dmitriy Antipov
9be35a1034
Added support for Reflection Raw mode for the color sensor to the simulator (#1017)
* redesigned-code-to-support-ref-raw

Code that adds reflection raw support for the color sensor. The range of values for this is from 0 to 1023, because analog to digital converter is 10 bits. In fact, the color sensor gives values ​​of about 400 - 700, but I decided to leave the range, which could theoretically be. For other cases (reflections and ambient lighting), the range remains from 0 to 100. The average value when setting the mode in the simulator is displayed as 512, for other modes 50%.

* block-description-update

Block description update, as it did not take into account the mode of raw reflection values.
2023-05-05 15:54:56 -07:00
Dmitriy Antipov
2ca706df70
Fix music images items in other languages (#1014)
* correction-of-displaying-pictures-in-different languages

Correction of displaying pictures in different languages. The category options values were translated into different languages and the translated values could not be checked against the values from icon.jres.

* element-layout-fixes

Уlement layout fixes, for more readable blocks

* Update fieldeditors/field_music.ts

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>

* Update fieldeditors/field_music.ts

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>

* tag-lang-tag-for-languages-other-than-en

The tag is not needed for English, because in the html tag it is already always set.

---------

Co-authored-by: Joey Wunderlich <jwunderl@users.noreply.github.com>
2023-05-05 15:50:04 -07:00
Dmitriy Antipov
dd415019c4
renderPorts-extra-checks-before-print (#1020)
When the program starts, when the showBoot() function is launched, the screenMode is checked and the showPorts function is launched, which in turn executes the renderPorts() function in a loop. While renderPorts is running, the screenMode may change, for example to ShowLines (when showString() was run). It may turn out that the mode has changed, and the renderPorts method has not been fully executed ... in the future, it will draw its own graphics on the screen, although we do not expect to see them already, because. a regime change has occurred. I added checks inside the function before displaying.
2023-05-05 15:46:43 -07:00
Joey Wunderlich
20581513b1 1.4.31 2023-04-29 17:22:20 -07:00
Dmitriy Antipov
1652fc5ffa
fix-bg-color (#1016) 2023-04-29 17:21:48 -07:00
Joey Wunderlich
8a1b6452bd
unpin beta (#1015) 2023-04-28 14:26:34 -07:00
Joey Wunderlich
a6712960db 1.4.30 2023-04-26 09:30:55 -07:00
Joey Wunderlich
bac70eb177 bump to pick up in ctx translations fix 2023-04-26 09:30:05 -07:00
Joey Wunderlich
830f5ffd77 1.4.29 2023-04-25 16:35:05 -07:00
Joey Wunderlich
aac5edd64b bump pxt to latest 7.2.* to pick up crowdin / build fixes 2023-04-25 16:25:21 -07:00
Joey Wunderlich
a54007d9ae 1.4.28 2023-04-25 14:56:21 -07:00
Joey Wunderlich
3952cb4858 1.4.27 2023-04-25 12:21:03 -07:00
Joey Wunderlich
0226888441
Change crowdin project to new name (kindscript->makecode) (#1013) 2023-04-25 12:20:42 -07:00
Joey Wunderlich
1373e9c0bc 1.4.26 2023-04-25 12:08:04 -07:00
Dmitriy Antipov
cabcb048e3
Troubleshooting updates v1.4.25 (#1012)
* sim_fix

ES version update

* fieldeditors-es-upgrade-to-es2017

Update es to fix issue with fieldeditors.

* editor-es-upgrade-to-es2017

Update es that fixes an issue with the editor.

* editor-download-dialog-fix

Solving a download error that arose due to problems with the buttons in the dialog box.

* return_field_motors

We return the fieldmotors field, because it is necessary about the choice of types of motors: medium, large, one or two.

* update-fields-for-motor-blocks

Set the blocks to the fieldmotors field. Change the name of the blocks for the motors.

* enable-debugger

Instead of the slowmo mode, which was before, a debugger was added, in which slowmo is present.

* fix-field-music

It turned out to update the fieldmusic menu. The menu is now displayed in the correct position.

* Update field_music.ts

* fix-field-brickbutton

Fixed issue with button select menu position from ev3 brick.

* Update dialogs.tsx

* Update field_motors.ts

Repartition of Label for fieldmotos, now it's more readable, it's better.

* motors-new-icon

Created new icons for motors for dropdown image.

* remove-ai-files-for-motors-icon

Remove ai image files for motors
2023-04-25 12:06:54 -07:00
microsoft-github-policy-service[bot]
512a441bca
Microsoft mandatory file (#1007)
Co-authored-by: microsoft-github-policy-service[bot] <77245923+microsoft-github-policy-service[bot]@users.noreply.github.com>
2022-08-30 10:35:02 -07:00
pelikhan
b4a18f260d lock beta to 1.4.24 2022-01-29 13:29:33 -08:00
pelikhan
6b3f2da72c 1.4.25 2022-01-29 12:05:31 -08:00
Dmitriy Antipov
b9b21328b1
return_blocks (#1003)
These blocks are present in the stable version, but not in the beta.
2021-11-29 09:57:33 -08:00
Richard Knoll
bef4ebac43
Updating npm dependencies and getting the build to work (#1001)
* Updating npm dependencies and getting the build to work

* update node in github actions to 14.x
2021-09-22 15:51:32 -07:00
pelikhan
617fdeb747 1.4.24 2021-09-10 11:21:42 -07:00
Dmitriy Antipov
c1aead1aa9
fix invert motor angle metod (#999) 2021-09-09 14:11:06 -07:00
Richard Knoll
bd0cf05693
Adding gh-actions workflows (#995)
* Adding gh-actions workflows

* Removing travis

* Handle tags also
2021-01-27 14:57:14 -08:00
Galen Nickel
faae7133f5
Word changes to reduce policheck hits (#992) 2020-11-06 13:09:53 -08:00
Peli de Halleux
5289850351 bump to v1.2.31 2020-10-02 23:42:38 +02:00
Peli de Halleux
ba6e2f7174 enable french 2020-10-02 23:13:04 +02:00
peli
7c5dfc474f update version to v1.2.30 2020-09-20 23:47:53 -07:00
peli
5ab3a6ae96 1.4.23 2020-09-10 23:40:51 -07:00
Maciej Mroziński
ed2e1f23e9
Change timeout 1s -> 5s to reduce Timeout errors (#988) 2020-09-11 08:25:12 +02:00
Maciej Mroziński
a157943bf7
Read default volume from device settings at start (#987) 2020-09-09 12:06:33 -07:00
peli
40aaf0fb18 1.4.22 2020-09-08 23:54:42 -07:00
Maciej Mroziński
b26cf289c3
Change sound volume to level (#986) 2020-09-08 23:53:33 -07:00
Peli de Halleux
f0821f8d6c cherry-pick Cooperate (#985)
* cooperate pause

* fix math

* update lastPause before pausing

* faster cooperation

Co-authored-by: Peli de Halleux <peli@DESKTOP-5B7QRAM.corp.microsoft.com>
2020-08-21 06:09:01 +02:00
Richard Knoll
1db61720fc
Adding config file for service worker (#982) 2020-03-27 15:16:56 -07:00
shakao
ec2e561427
Updates for policheck (#975) 2020-02-24 09:39:25 -08:00
Peli
36d99c8a55 updated js logo 2020-02-09 21:50:52 -08:00
61 changed files with 772 additions and 715 deletions

40
.github/workflows/pxt-buildmain.yml vendored Normal file
View File

@ -0,0 +1,40 @@
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

31
.github/workflows/pxt-buildpr.yml vendored Normal file
View File

@ -0,0 +1,31 @@
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

39
.github/workflows/pxt-buildpush.yml vendored Normal file
View File

@ -0,0 +1,39 @@
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

View File

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

41
SECURITY.md Normal file
View File

@ -0,0 +1,41 @@
<!-- 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": "v"
"appref": "v1.4"
}

View File

@ -21,7 +21,7 @@ https://youtu.be/VIq8-6Egtqs
## Supported browsers
* Chrome desktop, version 77 and higher, Windows 10 or Mac OS.
* [Edge Insider desktop](https://www.microsoftedgeinsider.com), version 77 and higher, Windows 10 or Mac OS.
* [Microsoft Edge Insider desktop](https://www.microsoftedgeinsider.com), version 77 and higher, Windows 10 or Mac OS.
To make sure your browser is up to date, go to the '...' menu, click "Help" then "About".

View File

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

View File

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

View File

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

View File

@ -1 +1,27 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000" viewBox="0 0 1000 1000"><path class="st1" d="M843.77886 524.88744 880.276 501.83162 843.77886 478.86523c-17.00235-10.68208-30.88888-21.80904-41.21473-33.11451-9.88096-10.68206-18.15968-24.12333-24.65806-39.87966-6.85421-16.37895-11.75036-36.49708-14.5986-59.64157-3.0279-24.47957-4.53992-53.85527-4.53992-87.23694 0-34.8058-0.71245-60.79853-2.2264-79.49216-1.69206-21.72037-5.51915-37.92159-11.4832-49.49384-7.29949-14.06465-18.07062-23.94561-31.95715-29.46476-9.97002-3.916526-23.50072-6.854208-41.21512-8.81267-6.23121-0.89056-11.12736-3.740352-15.84501-9.524735-4.89614-5.964035-7.38854-15.311043-7.38854-27.862527 0-18.248344 3.82941-36.0518 49.84968-36.0518 28.30741 0 53.23225 5.607817 74.1515 16.735171 20.6517 10.949237 36.40803 26.171235 48.33612 46.556149 11.92847 20.384922 18.07062 44.241472 18.33779 71.035712 2.84979 158.1836 5.78593 189.8736 8.18966 199.93266 6.76518 28.04064 17.0019 49.40478 31.156 65.16073 12.72932 14.15371 28.21841 26.79424 46.02186 37.47631 12.90734 7.74439 22.25434 15.13294 27.95127 21.98715 1.603 1.87017 5.16331 8.10062 5.16331 24.65768 0 17.09139-5.34106 27.95158-17.35854 35.34012-26.97238 16.55706-46.37811 31.067-59.19637 44.33053-14.4209 14.86578-24.56869 33.47034-30.17683 55.19072-4.98481 19.40568-7.92251 46.73387-8.81267 83.40907-0.89056 34.44996-1.87018 77.53409-2.93885 129.25317-0.89056 41.92717-13.61976 74.24056-38.81139 98.89824-25.28105 24.65767-58.66273 36.67519-101.92497 36.67519-18.15968 0-31.60095-3.47319-39.79061-10.23717-6.8546-5.69688-10.05907-14.24277-10.05907-26.8833 0-8.01156 1.33584-14.95483 4.09464-21.2751 2.40451-5.43008 5.16331-9.43567 8.36779-11.92808 3.0279-2.31546 6.40931-3.6513 10.68206-4.18408 18.42647-2.49357 32.22434-5.60782 42.37208-9.70285 14.1541-5.78592 25.28106-16.82422 32.13527-31.86811 5.51915-11.92808 8.90173-27.86252 10.41529-48.42517 1.33584-17.89251 1.95924-43.08451 1.95924-76.82202 0.71244-47.26822 3.38412-84.3883 8.1006-110.38143 4.1837-23.58977 12.19526-43.88564 23.67845-60.44269 11.57224-16.82423 29.46475-32.9364 53.23226-47.89122zm-680.5 125.78114c2.49357 10.05907 5.34104 41.74907 8.18967 199.93305 0.27104 26.79424 6.49798 50.65079 18.33741 71.03571 11.83941 20.38492 27.68441 35.60691 48.33649 46.55615 20.91887 11.12697 45.84371 16.73517 74.15151 16.73517 46.02182 0 49.84968-17.80346 49.84968-36.05219 0-12.55148-2.49357-21.98716-7.38855-27.86213-4.71803-5.69727-9.61379-8.63495-15.845-9.52512-17.7144-1.95924-31.24511-4.89576-41.12606-8.81268-13.88692-5.51915-24.65767-15.40011-31.95716-29.46476-5.96443-11.57224-9.79191-27.68441-11.4832-49.49345-1.51395-18.78268-2.2264-44.7758-2.2264-79.49255 0-33.38128-1.51395-62.75698-4.53992-87.23693-2.93885-23.1445-7.83344-43.17319-14.68765-59.55253-6.49838-15.75594-14.7771-29.19758-24.65806-39.87966-10.4149-11.30508-24.21239-22.43243-41.21473-33.1145l-36.49708-22.96638 36.49708-23.05544c23.67844-14.95482 41.57095-31.06699 53.32132-47.89122 11.48318-16.55744 19.49474-36.85331 23.67843-60.44309 4.71803-25.99273 7.38856-63.20226 8.10061-110.38142 0-33.73751 0.62339-58.84007 1.95923-76.82164 1.51395-20.65209 4.89576-36.49708 10.41491-48.42556 6.85461-15.04387 17.98157-26.08218 32.04623-31.8681 10.05907-4.09464 23.9456-7.299501 42.37245-9.702847 4.27275-0.534336 7.65534-1.870176 10.68207-4.183696 3.20602-2.493568 6.05311-6.498382 8.3674-11.928477 2.84979-6.409315 4.18408-13.352592 4.18408-21.364145 0-12.640529-3.20602-21.186033-10.05907-26.883294-8.27872-6.765158-21.63132-10.236793-39.87967-10.236793-43.35168 0-76.73296 12.017139-101.92497 36.675192-25.19201 24.657677-37.92121 56.97067-38.81138 98.89785-1.06867 51.71908-2.04829 94.8036-2.93885 129.25317-0.97962 36.6752-3.82941 64.00339-8.81267 83.40908-5.60821 21.72036-15.75594 40.32494-30.17682 55.19071-12.9077 13.26392-32.31339 27.77347-59.285742 44.33092-12.017139 7.38816-17.358176 18.24835-17.358176 35.33974 0 16.64611 3.651296 22.78827 5.162925 24.65767 5.697261 6.76555 15.043878 14.15371 27.951586 21.98754 17.803457 10.68207 33.292227 23.32222 46.021807 37.47593 14.24277 15.84539 24.3909 37.12048 31.24511 65.16072z" style="stroke-width:11;stroke:#000"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 630 630">
<!--
The MIT License (MIT)
Copyright (c) 2011 Christopher Williams <chris@iterativedesigns.com>,
Manuel Strehl <boldewyn@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
<path d="M 0 0 L 0 630 L 630 630 L 630 0 L 0 0 z M 479.45312 285.8457 C 517.09063 285.8457 544.15617 298.95789 563.60742 333.21289 L 517.51172 362.81445 C 507.36172 344.63195 496.36813 337.44336 479.45312 337.44336 C 462.11437 337.44336 451.11914 348.4382 451.11914 362.81445 C 451.11914 380.57695 462.11508 387.76547 487.48633 398.76172 L 502.28711 405.10547 C 552.61211 426.67422 580.94531 448.66242 580.94531 498.13867 C 580.94531 551.42617 539.07969 580.60352 482.83594 580.60352 C 427.85969 580.60352 392.33625 554.38711 375 520.13086 L 423.20703 492.21875 C 435.89703 512.9425 452.38961 528.16602 481.56836 528.16602 C 506.09961 528.16602 521.74219 515.90087 521.74219 498.98438 C 521.74219 478.68563 505.67172 471.4957 478.60547 459.6582 L 463.80859 453.31055 C 421.09359 435.1293 392.75781 412.29398 392.75781 364.08398 C 392.75781 319.68023 426.58938 285.8457 479.45312 285.8457 z M 283.63867 289.23047 L 342.8418 289.23047 L 342.8418 491.36719 C 342.8418 552.68719 306.89828 580.59961 254.45703 580.59961 C 207.09789 580.59961 179.60793 556.07214 165.65234 526.47266 L 165.65039 526.47461 L 165.65039 526.46875 C 165.65101 526.47007 165.65172 526.47134 165.65234 526.47266 L 213.86328 497.29688 C 223.16453 513.78813 231.62492 527.74023 251.91992 527.74023 C 271.37367 527.74023 283.63867 520.12955 283.63867 490.5293 L 283.63867 289.23047 z "/>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

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

View File

@ -1,4 +1,5 @@
import * as React from "react";
import { canUseWebSerial, enableWebSerialAsync } from "./deploy";
import { projectView } from "./extension";
@ -21,7 +22,7 @@ export function bluetoothTryAgainAsync(): Promise<void> {
function enableWebSerialAndCompileAsync() {
return enableWebSerialAsync()
.then(() => Promise.delay(500))
.then(() => pxt.U.delay(500))
.then(() => projectView.compile());
}
@ -52,11 +53,12 @@ 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.
// "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;
const docUrl = (pxt.appTarget.appTheme.usbDocs ? pxt.appTarget.appTheme.usbDocs : false);
const jsx =
<div className="ui grid stackable">
@ -118,7 +120,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",
@ -126,20 +128,19 @@ export function showUploadDialogAsync(fn: string, url: string, _confirmAsync: (o
pxt.tickEvent("bluetooth.enable");
explainWebSerialPairingAsync()
.then(() => enableWebSerialAndCompileAsync())
.done();
}
} : undefined, downloadAgain ? {
}, downloadAgain && {
label: fn,
icon: "download",
className: "lightgrey focused",
url,
fileName: fn
} : undefined, docUrl ? {
}, docUrl && {
label: lf("Help"),
icon: "help",
className: "lightgrey",
url: docUrl
} : undefined]
}]
//timeout: 20000
}).then(() => { });
}

View File

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

View File

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

View File

@ -120,20 +120,17 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.
Blockly.DropDownDiv.setColour('#ffffff', '#dddddd');
// 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));
// 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());
}
}
/**
@ -157,5 +154,12 @@ 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_);
}
};
}

View File

@ -5,10 +5,14 @@ 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) {
@ -33,11 +37,21 @@ 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'; // Grey
case 'ColorSensorColor.None': return '#dfe6e9';
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
@ -64,7 +78,7 @@ export class FieldColorEnum extends pxtblockly.FieldColorNumber implements Block
}
this.value_ = colour;
if (this.sourceBlock_) {
this.sourceBlock_.setColour(colour, colour, colour);
this.sourceBlock_.setColour(colour);
}
}
}

File diff suppressed because one or more lines are too long

View File

@ -11,6 +11,7 @@ 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;
@ -23,17 +24,17 @@ 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) || 380;
this.width_ = parseInt(options.width) || 450;
this.setText = Blockly.FieldDropdown.prototype.setText;
this.updateSize_ = (Blockly.Field as any).prototype.updateSize_;
this.updateTextNode_ = Blockly.Field.prototype.updateTextNode_;
if (!pxt.BrowserUtils.isIE() && !soundCache) {
soundCache = JSON.parse(pxtTargetBundle.bundledpkgs['music']['sounds.jres']);
}
if (!soundIconCache) {
soundIconCache = JSON.parse(pxtTargetBundle.bundledpkgs['music']['icons.jres']);
soundIconCacheArray = Object.entries(soundIconCache).filter(el => el[0] !== "*");
}
}
@ -50,14 +51,17 @@ 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();
let dropdownDiv = Blockly.DropDownDiv.getContentDiv() as HTMLElement;
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();
//options.sort(); // Do not need to use to not apply sorting in different languages
// Create categoies
const categories = this.getCategories(options);
@ -68,7 +72,7 @@ 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_.getColourTertiary();
categoriesDiv.style.backgroundColor = (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary();
categoriesDiv.className = 'blocklyMusicFieldCategories';
this.refreshCategories(categoriesDiv, categories);
@ -82,30 +86,18 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
dropdownDiv.appendChild(categoriesDiv);
dropdownDiv.appendChild(contentDiv);
Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), this.sourceBlock_.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));
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));
// Update colour to look selected.
if (this.sourceBlock_.isShadow()) {
this.savedPrimary_ = this.sourceBlock_.getColour();
this.sourceBlock_.setColour(this.sourceBlock_.getColourTertiary(),
this.sourceBlock_.getColourSecondary(), this.sourceBlock_.getColourTertiary());
} else if (this.box_) {
this.box_.setAttribute('fill', this.sourceBlock_.getColourTertiary());
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());
}
}
@ -122,7 +114,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
}
refreshCategories(categoriesDiv: Element, categories: string[]) {
// Show category dropdown.
// Show category dropdown.
for (let i = 0; i < categories.length; i++) {
const category = categories[i];
@ -138,6 +130,7 @@ 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_);
@ -151,7 +144,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.
@ -186,11 +179,11 @@ 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_.getColourTertiary();
backgroundColor = (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary();
button.setAttribute('aria-selected', 'true');
}
button.style.backgroundColor = backgroundColor;
button.style.borderColor = this.sourceBlock_.getColourTertiary();
button.style.borderColor = (this.sourceBlock_ as Blockly.BlockSvg).getColourTertiary();
Blockly.bindEvent_(button, 'click', this, this.buttonClick_);
Blockly.bindEvent_(button, 'mouseup', this, this.buttonClick_);
// These are applied manually instead of using the :hover pseudoclass
@ -215,15 +208,27 @@ 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(category);
//buttonImg.alt = icon.alt;
buttonImg.src = this.getSoundIcon(categoryIndex);
// 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);
@ -238,12 +243,19 @@ 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;
@ -311,9 +323,9 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
pxsim.AudioContextManager.stop();
}
private getSoundIcon(category: string) {
if (soundIconCache && soundIconCache[category]) {
return soundIconCache[category].icon;
private getSoundIcon(indexCategory: number) {
if (soundIconCacheArray && soundIconCacheArray[indexCategory]) {
return soundIconCacheArray[indexCategory][1].icon;
}
return undefined;
}

View File

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

View File

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

12
libs/base/shims.d.ts vendored
View File

@ -87,6 +87,12 @@ declare interface Buffer {
*/
//% shim=BufferMethods::write
write(dstOffset: int32, src: Buffer): void;
/**
* Compute k-bit FNV-1 non-cryptographic hash of the buffer.
*/
//% shim=BufferMethods::hash
hash(bits: int32): uint32;
}
declare namespace control {
@ -94,14 +100,14 @@ declare namespace control {
* Create a new zero-initialized buffer.
* @param size number of bytes in the buffer
*/
//% shim=control::createBuffer
//% deprecated=1 shim=control::createBuffer
function createBuffer(size: int32): Buffer;
/**
* Create a new buffer with UTF8-encoded string
* @param str the string to put in the buffer
*/
//% shim=control::createBufferFromUTF8
//% deprecated=1 shim=control::createBufferFromUTF8
function createBufferFromUTF8(str: string): Buffer;
}
declare namespace loops {
@ -198,6 +204,8 @@ declare namespace control {
*/
//% shim=control::dmesgValue
function dmesgValue(v: any): void;
}
declare namespace control {
/**
* 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).
* Measure the ambient or reflected light value from 0 (darkest) to 100 (brightest). In raw reflection light mode, the range will be different.
* @param sensor the color sensor port
*/
//% help=sensors/color-sensor/light

View File

@ -1,5 +1,3 @@
namespace sensors {
/**
@ -9,9 +7,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"]'
//% color.fieldOptions.colours='["#f12a21", "#ffd01b", "#006db3", "#00934b", "#000000", "#6c2d00", "#ffffff", "#dfe6e9"]'
//% color.fieldOptions.columns=2 color.fieldOptions.className='legoColorPicker'
export function __colorEnumPicker(color: ColorSensorColor): number {
return color;
}
}
}

11
libs/core/cooperate.ts Normal file
View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -124,7 +124,7 @@ namespace motors {
export function stopAll() {
const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
writePWM(b);
pause(1);
control.cooperate();
}
/**
@ -136,7 +136,7 @@ namespace motors {
//% help=motors/reset-all
export function resetAll() {
reset(Output.ALL)
pause(1);
control.cooperate();
}
interface MoveSchedule {
@ -196,6 +196,7 @@ namespace motors {
*/
//% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake=toggleOnOff"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=60 blockGap=8
//% group="Properties"
//% help=motors/motor/set-brake
@ -210,6 +211,7 @@ namespace motors {
*/
//% blockId=outputMotorSetPauseMode block="set %motor|pause on run %brake=toggleOnOff"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=60 blockGap=8
//% group="Properties"
setPauseOnRun(value: boolean) {
@ -217,11 +219,12 @@ namespace motors {
this._pauseOnRun = value;
}
/**
/**
* Inverts the motor polarity
*/
//% blockId=motorSetInverted block="set %motor|inverted %reversed=toggleOnOff"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=59 blockGap=8
//% group="Properties"
//% help=motors/motor/set-inverted
@ -234,11 +237,12 @@ namespace motors {
return this._inverted ? -1 : 1;
}
/**
/**
* 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.fieldOptions.decompileLiterals=1
//% weight=1 blockGap=8
//% group="Properties"
//% millis.defl=200 millis.min=0 millis.max=500
@ -269,7 +273,7 @@ namespace motors {
if (this._brake && this._brakeSettleTime > 0)
pause(this._brakeSettleTime);
else {
pause(1);
control.cooperate();
}
}
@ -280,7 +284,7 @@ namespace motors {
// allow robot to settle
this.settle();
} else {
pause(1);
control.cooperate();
}
}
@ -344,6 +348,7 @@ namespace motors {
//% weight=100 blockGap=8
//% group="Move"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% expandableArgumentMode=toggle
//% help=motors/motor/run
run(speed: number, value: number = 0, unit: MoveUnit = MoveUnit.MilliSeconds) {
@ -357,7 +362,7 @@ namespace motors {
// special: 0 is infinity
if (schedule.steps[0] + schedule.steps[1] + schedule.steps[2] == 0) {
this._run(schedule.speed);
pause(1);
control.cooperate();
return;
}
@ -393,6 +398,7 @@ namespace motors {
//% weight=99 blockGap=8
//% group="Move"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% help=motors/motor/ramp
//% inlineInputMode=inline
//% expandableArgumentMode=toggle
@ -422,6 +428,7 @@ namespace motors {
*/
//% blockId=outputMotorsetRunRamp block="set %motor|run %ramp to $value||$unit"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=21 blockGap=8
//% group="Properties"
//% help=motors/motor/set-run-phase
@ -493,6 +500,7 @@ namespace motors {
*/
//% blockId=outputMotorSetRegulated block="set %motor|regulated %value=toggleOnOff"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=58 blockGap=8
//% group="Properties"
//% help=motors/motor/set-regulated
@ -518,6 +526,7 @@ namespace motors {
*/
//% blockId=motorPauseUntilRead block="pause until %motor|ready"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=90 blockGap=8
//% group="Move"
pauseUntilReady(timeOut?: number) {
@ -576,7 +585,8 @@ namespace motors {
*/
//% blockId=motorSpeed block="%motor|speed"
//% motor.fieldEditor="motors"
//% weight=72
//% motor.fieldOptions.decompileLiterals=1
//% weight=72
//% blockGap=8
//% group="Counters"
//% help=motors/motor/speed
@ -591,13 +601,14 @@ namespace motors {
*/
//% blockId=motorAngle block="%motor|angle"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=70
//% blockGap=8
//% group="Counters"
//% help=motors/motor/angle
angle(): number {
this.init();
return getMotorData(this._port).count;
return getMotorData(this._port).count * this.invertedFactor();
}
/**
@ -605,6 +616,7 @@ namespace motors {
*/
//% blockId=motorClearCount block="clear %motor|counters"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=68
//% blockGap=8
//% group="Counters"
@ -633,6 +645,7 @@ namespace motors {
*/
//% blockId=motorPauseUntilStall block="pause until %motor|stalled"
//% motor.fieldEditor="motors"
//% motor.fieldOptions.decompileLiterals=1
//% weight=89
//% group="Move"
//% help=motors/motor/pause-until-stalled
@ -656,28 +669,28 @@ namespace motors {
}
}
//% whenUsed fixedInstance block="large motor A" jres=icons.portA
//% whenUsed fixedInstance block="large motor A" jres=icons.motorLargePortA
export const largeA = new Motor(Output.A, true);
//% whenUsed fixedInstance block="large motor B" jres=icons.portB
//% whenUsed fixedInstance block="large motor B" jres=icons.motorLargePortB
export const largeB = new Motor(Output.B, true);
//% whenUsed fixedInstance block="large motor C" jres=icons.portC
//% whenUsed fixedInstance block="large motor C" jres=icons.motorLargePortC
export const largeC = new Motor(Output.C, true);
//% whenUsed fixedInstance block="large motor D" jres=icons.portD
//% whenUsed fixedInstance block="large motor D" jres=icons.motorLargePortD
export const largeD = new Motor(Output.D, true);
//% whenUsed fixedInstance block="medium motor A" jres=icons.portA
//% whenUsed fixedInstance block="medium motor A" jres=icons.motorMeduimPortA
export const mediumA = new Motor(Output.A, false);
//% whenUsed fixedInstance block="medium motor B" jres=icons.portB
//% whenUsed fixedInstance block="medium motor B" jres=icons.motorMeduimPortB
export const mediumB = new Motor(Output.B, false);
//% whenUsed fixedInstance block="medium motor C" jres=icons.portC
//% whenUsed fixedInstance block="medium motor C" jres=icons.motorMeduimPortC
export const mediumC = new Motor(Output.C, false);
//% whenUsed fixedInstance block="medium motor D" jres=icons.portD
//% whenUsed fixedInstance block="medium motor D" jres=icons.motorMeduimPortD
export const mediumD = new Motor(Output.D, false);
//% fixedInstances
@ -697,10 +710,10 @@ namespace motors {
}
/**
* 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,
* 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
* 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,
* 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
* to make your robot turn.
* @param speedLeft the speed on the left motor, eg: 50
* @param speedRight the speed on the right motor, eg: 50
@ -708,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="ports"
//% motors.fieldEditor="motors"
//% weight=96 blockGap=8
//% inlineInputMode=inline
//% group="Move"
@ -738,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="ports"
//% chassis.fieldEditor="motors"
//% weight=95
//% turnRatio.min=-200 turnRatio=200
//% inlineInputMode=inline
@ -811,16 +824,16 @@ namespace motors {
}
}
//% whenUsed fixedInstance block="B+C" jres=icons.portBC
//% whenUsed fixedInstance block="large motors B+C" jres=icons.dualMotorLargePortBC
export const largeBC = new SynchedMotorPair(Output.BC);
//% whenUsed fixedInstance block="A+D" jres=icons.portAD
//% whenUsed fixedInstance block="large motors A+D" jres=icons.dualMotorLargePortAD
export const largeAD = new SynchedMotorPair(Output.AD);
//% whenUsed fixedInstance block="A+B" jres=icons.portAB
//% whenUsed fixedInstance block="large motors A+B" jres=icons.dualMotorLargePortAB
export const largeAB = new SynchedMotorPair(Output.AB);
//% whenUsed fixedInstance block="C+D" jres=icons.portCD
//% whenUsed fixedInstance block="large motors C+D" jres=icons.dualMotorLargePortCD
export const largeCD = new SynchedMotorPair(Output.CD);
function reset(out: Output) {

View File

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

View File

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

View File

@ -13,7 +13,22 @@
namespace music {
uint8_t currVolume = 50;
int _readSystemVolume() {
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;
int writeDev(void *data, int size) {
@ -37,6 +52,18 @@ void setVolume(int 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_TONE 1
#define SOUND_CMD_PLAY 2
@ -45,7 +72,7 @@ void setVolume(int volume) {
struct ToneCmd {
uint8_t cmd;
uint8_t vol;
uint8_t lvl;
uint16_t freq;
uint16_t duration;
};
@ -55,10 +82,26 @@ static void _stopSound() {
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) {
// https://github.com/mindboards/ev3sources/blob/78ebaf5b6f8fe31cc17aa5dce0f8e4916a4fc072/lms2012/c_sound/source/c_sound.c#L471
uint8_t level = _getVolumeLevel(volume, 13);
ToneCmd cmd;
cmd.cmd = SOUND_CMD_TONE;
cmd.vol = volume;
cmd.lvl = level;
cmd.freq = frequency;
cmd.duration = duration;
// (*SoundInstance.pSound).Busy = TRUE;
@ -122,7 +165,8 @@ void playSample(Buffer buf) {
stopUser();
pthread_mutex_lock(&pumpMutex);
*lmsSoundMMap = 1; // BUSY
uint8_t cmd[] = {SOUND_CMD_PLAY, (uint8_t)((currVolume / 33) + 1)};
// https://github.com/mindboards/ev3sources/blob/78ebaf5b6f8fe31cc17aa5dce0f8e4916a4fc072/lms2012/c_sound/source/c_sound.c#L605
uint8_t cmd[] = {SOUND_CMD_PLAY, _getVolumeLevel(currVolume, 8)};
writeDev(cmd, 2);
decrRC(currentSample);
currentSample = buf;
@ -201,4 +245,4 @@ Buffer buffer(Sound snd) {
void play(Sound snd) {
music::playSample(snd);
}
}
}

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

@ -13,6 +13,16 @@ declare namespace music {
//% weight=1 shim=music::setVolume
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.
* @param frequency pitch of the tone to play in Hertz (Hz), eg: Note.C

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,5 @@
self.setSimulatorWorkerOptions({
urls: [
"/sim/common-sim.js"
]
})

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,8 +5,8 @@ namespace pxsim.visuals {
export class ColorGridControl extends ControlView<ColorSensorNode> {
private group: SVGGElement;
private static colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey', 'white'];
private static colorValue = [5, 4, 2, 3, 1, 7, 6];
private static colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'brown', 'white', 'none'];
private static colorValue = [5, 4, 2, 3, 1, 7, 6, 0];
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', 'grey'];
const colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'brown'];
let cy = -4;
for (let c = 0; c < colorIds.length; c++) {
@ -33,12 +33,19 @@ namespace pxsim.visuals {
}
const whiteCircleWrapper = pxsim.svg.child(this.group, "g", { 'id': 'white-cirlce-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` });
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` });
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` });
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;
}

View File

@ -26,8 +26,12 @@ namespace pxsim.visuals {
return 131;
}
private getMaxValue() {
return 100;
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;
}
updateState() {
@ -35,10 +39,12 @@ namespace pxsim.visuals {
return;
}
const node = this.state;
const percentage = node.getValue();
const inversePercentage = this.getMaxValue() - percentage;
svg.setGradientValue(this.colorGradient, inversePercentage + "%");
this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}%`;
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 += `%`;
}
updateColorLevel(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) {
@ -47,7 +53,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.setColor(t * this.getMaxValue(state.getMode()));
}
getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) {

View File

@ -29,6 +29,7 @@ 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');

View File

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

View File

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