Compare commits

...

8 Commits

Author SHA1 Message Date
Peli de Halleux
df19c45c3a Merge remote-tracking branch 'origin/master' into pxtv50 2019-08-27 14:14:40 -07:00
Peli de Halleux
27a8bda31d fixing various typing issues 2019-03-06 08:36:43 -08:00
Peli de Halleux
cfdb113a21 more typing fixes 2019-03-06 08:32:18 -08:00
Peli de Halleux
f76a407027 various typing fixes 2019-03-06 08:02:09 -08:00
Peli de Halleux
e6cf490be2 removing feild editors moved to pxt 2019-03-04 21:02:29 -08:00
Peli de Halleux
2316009b64 Auto-gen of projects/summary 2019-03-04 20:53:54 -08:00
Peli de Halleux
f8ef7bb943 fix build issues 2019-03-04 20:50:15 -08:00
Peli de Halleux
a3e431c892 bump pxt 2019-03-04 20:44:01 -08:00
16 changed files with 170 additions and 269 deletions

View File

@ -1,9 +1,46 @@
# Projects # Projects
Here are some cool projects that you can build with your @boardname@! ```codecard
[
{
"name": "Getting Started",
"url": "/getting-started",
"imageUrl": "/static/lessons/firmware.png"
},
{
"name": "Tutorials",
"url": "/tutorials",
"imageUrl": "/static/tutorials/wake-up.png"
},
{
"name": "Design Engineering",
"url": "/design-engineering",
"imageUrl": "/static/lessons/make-it-move-without-wheels.png"
},
{
"name": "Coding",
"url": "/coding",
"imageUrl": "/static/lessons/autonomous-parking.png"
},
{
"name": "Maker",
"url": "/maker",
"imageUrl": "/static/lessons/make-a-sound-machine.png"
},
{
"name": "Videos",
"url": "/videos",
"imageUrl": "https://legoeducation.videomarketingplatform.co/27288170/35719444/5d009e5f93fbf479c2e5ed2bf87a7990/thumbnail.png"
}
]
```
## Basic ## See Also
Basic projects to build with your EV3 Brick. [Getting Started](/getting-started),
[Tutorials](/tutorials),
[Design Engineering](/design-engineering),
[Coding](/coding),
[Maker](/maker),
[Videos](/videos)
Coming soon.

35
docs/projects/SUMMARY.md Normal file
View File

@ -0,0 +1,35 @@
# Projects
* [Getting Started](/getting-started)
* [Prepare](https://makecode.mindstorms.com/troubleshoot)
* [Try](/getting-started/try)
* [Use](/getting-started/use)
* [Tutorials](/tutorials)
* [Wake Up!](/tutorials/wake-up)
* [Make an Animation](/tutorials/make-an-animation)
* [What Animal Am I?](/tutorials/what-animal-am-i)
* [Music Brick](/tutorials/music-brick)
* [Run Motors](/tutorials/run-motors)
* [Touch to Run](/tutorials/touch-to-run)
* [Touch Sensor Values](/tutorials/touch-sensor-values)
* [What Color?](/tutorials/what-color)
* [Line Following](/tutorials/line-following)
* [Red Light, Green Light](/tutorials/redlight-greenlight)
* [Security Alert](/tutorials/security-alert)
* [Design Engineering](/design-engineering)
* [Make It Move Without Wheels](/design-engineering/make-it-move)
* [Make It Smarter and Faster](/design-engineering/make-it-smarter)
* [Make a System that Communicates](/design-engineering/make-it-communicate)
* [Coding](/coding)
* [Autonomous Parking](/coding/autonomous-parking)
* [Object Detection](/coding/object-detection)
* [Line Detection](/coding/line-detection)
* [Maker](/maker)
* [Make A Sound Machine](/maker/sound-machine)
* [Make A Security Gadget](/maker/security-gadget)
* [Videos](/videos)
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=5d009e5f93fbf479c2e5ed2bf87a7990&source=embed&photo%5fid=35719444)
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=2008a566f1fb034d58d5ebe19ba8621f&source=embed&photo%5fid=35719467)
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=629730c938e452f0fd7653fbc4708166&source=embed&photo%5fid=35719470)
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=3513a83b87fe536b2dc512237465fd1b&source=embed&photo%5fid=35719471)
* [undefined](https://legoeducation.videomarketingplatform.co/v.ihtml/player.html?token=5c594c2373367f7870196f519f3bfc7a&source=embed&photo%5fid=35719472)

View File

@ -33,7 +33,7 @@ export function initAsync() {
canHID = false canHID = false
} else { } else {
const forceHexDownload = /forceHexDownload/i.test(window.location.href); const forceHexDownload = /forceHexDownload/i.test(window.location.href);
if (pxt.Cloud.isLocalHost() && pxt.Cloud.localToken && !forceHexDownload) if (pxt.BrowserUtils.isLocalHost() && pxt.Cloud.localToken && !forceHexDownload)
canHID = true canHID = true
} }

View File

@ -3,9 +3,7 @@
import { FieldPorts } from "./field_ports"; import { FieldPorts } from "./field_ports";
import { FieldMotors } from "./field_motors"; import { FieldMotors } from "./field_motors";
import { FieldSpeed } from "./field_speed";
import { FieldBrickButtons } from "./field_brickbuttons"; import { FieldBrickButtons } from "./field_brickbuttons";
import { FieldTurnRatio } from "./field_turnratio";
import { FieldColorEnum } from "./field_color"; import { FieldColorEnum } from "./field_color";
import { FieldMusic } from "./field_music"; import { FieldMusic } from "./field_music";
@ -19,15 +17,9 @@ pxt.editor.initFieldExtensionsAsync = function (opts: pxt.editor.FieldExtensionO
}, { }, {
selector: "motors", selector: "motors",
editor: FieldMotors editor: FieldMotors
}, {
selector: "speed",
editor: FieldSpeed
}, { }, {
selector: "brickbuttons", selector: "brickbuttons",
editor: FieldBrickButtons editor: FieldBrickButtons
}, {
selector: "turnratio",
editor: FieldTurnRatio
}, { }, {
selector: "colorenum", selector: "colorenum",
editor: FieldColorEnum editor: FieldColorEnum

View File

@ -121,7 +121,7 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.
Blockly.DropDownDiv.setColour('#ffffff', '#dddddd'); Blockly.DropDownDiv.setColour('#ffffff', '#dddddd');
// Calculate positioning based on the field position. // Calculate positioning based on the field position.
var scale = this.sourceBlock_.workspace.scale; var scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
var bBox = { width: this.size_.width, height: this.size_.height }; var bBox = { width: this.size_.width, height: this.size_.height };
bBox.width *= scale; bBox.width *= scale;
bBox.height *= scale; bBox.height *= scale;
@ -131,7 +131,7 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.
var secondaryX = primaryX; var secondaryX = primaryX;
var secondaryY = position.top; var secondaryY = position.top;
// Set bounds to workspace; show the drop-down. // Set bounds to workspace; show the drop-down.
(Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode); (Blockly.DropDownDiv as any).setBoundsElement((<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).getParentSvg().parentNode);
(Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY, (Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY,
this.onHide_.bind(this)); this.onHide_.bind(this));
} }
@ -152,9 +152,10 @@ export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.
* Callback for when the drop-down is hidden. * Callback for when the drop-down is hidden.
*/ */
private onHide_ = function () { private onHide_ = function () {
Blockly.DropDownDiv.content_.removeAttribute('role'); const content = Blockly.DropDownDiv.getContentDiv();
Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup'); content.removeAttribute('role');
Blockly.DropDownDiv.content_.removeAttribute('aria-activedescendant'); content.removeAttribute('aria-haspopup');
Blockly.DropDownDiv.getContentDiv().style.width = ''; content.removeAttribute('aria-activedescendant');
content.style.width = '';
}; };
} }

View File

@ -53,7 +53,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
this.arrow_.setAttributeNS('http://www.w3.org/1999/xlink', this.arrow_.setAttributeNS('http://www.w3.org/1999/xlink',
'xlink:href', (Blockly.FieldDropdown as any).DROPDOWN_SVG_DATAURI); 'xlink:href', (Blockly.FieldDropdown as any).DROPDOWN_SVG_DATAURI);
this.arrow2_ = Blockly.utils.createSvgElement('image', { this.arrow2_ = <SVGImageElement>Blockly.utils.createSvgElement('image', {
'height': (this as any).arrowSize_ + 'px', 'height': (this as any).arrowSize_ + 'px',
'width': (this as any).arrowSize_ + 'px' 'width': (this as any).arrowSize_ + 'px'
}); });
@ -79,7 +79,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
}, },
this.fieldGroup_); this.fieldGroup_);
fieldX += 10; // size of first group. fieldX += 10; // size of first group.
this.textElement2_ = Blockly.utils.createSvgElement('text', this.textElement2_ = <SVGTextElement>Blockly.utils.createSvgElement('text',
{ {
'class': (this as any).className_, 'class': (this as any).className_,
'x': fieldX, 'x': fieldX,
@ -89,7 +89,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
this.fieldGroup_); this.fieldGroup_);
this.updateEditable(); this.updateEditable();
this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_); (this.sourceBlock_ as Blockly.BlockSvg).getSvgRoot().appendChild(this.fieldGroup_);
// Force a render. // Force a render.
this.render_(); this.render_();
this.size_.width = 0; this.size_.width = 0;
@ -99,7 +99,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
// Add second dropdown // Add second dropdown
if (this.shouldShowRect_()) { if (this.shouldShowRect_()) {
this.box_ = Blockly.utils.createSvgElement('rect', { this.box_ = <SVGRectElement>Blockly.utils.createSvgElement('rect', {
'rx': (Blockly.BlockSvg as any).CORNER_RADIUS, 'rx': (Blockly.BlockSvg as any).CORNER_RADIUS,
'ry': (Blockly.BlockSvg as any).CORNER_RADIUS, 'ry': (Blockly.BlockSvg as any).CORNER_RADIUS,
'x': 0, 'x': 0,
@ -112,7 +112,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
'fill-opacity': 1 'fill-opacity': 1
}, null); }, null);
this.fieldGroup_.insertBefore(this.box_, this.textElement_); this.fieldGroup_.insertBefore(this.box_, this.textElement_);
this.box2_ = Blockly.utils.createSvgElement('rect', { this.box2_ = <SVGRectElement>Blockly.utils.createSvgElement('rect', {
'rx': (Blockly.BlockSvg as any).CORNER_RADIUS, 'rx': (Blockly.BlockSvg as any).CORNER_RADIUS,
'ry': (Blockly.BlockSvg as any).CORNER_RADIUS, 'ry': (Blockly.BlockSvg as any).CORNER_RADIUS,
'x': 0, 'x': 0,
@ -149,9 +149,9 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
getFirstValueI11n(value: string) { getFirstValueI11n(value: string) {
const firstValue = this.getFirstValue(value); const firstValue = this.getFirstValue(value);
const motorOptions = { const motorOptions = {
'medium motor': lf('medium motor'), 'medium motor': lf("medium motor"),
'large motor': lf('large motor'), 'large motor': lf("large motor"),
'large motors': lf('large motors') 'large motors': lf("large motors")
} }
return motorOptions[firstValue]; return motorOptions[firstValue];
} }
@ -233,8 +233,8 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
if (this.textElement2_) { if (this.textElement2_) {
this.textElement2_.parentNode.appendChild(this.arrow2_); this.textElement2_.parentNode.appendChild(this.arrow2_);
} }
if (this.sourceBlock_ && this.sourceBlock_.rendered) { if (this.sourceBlock_ && (<Blockly.BlockSvg>this.sourceBlock_).rendered) {
this.sourceBlock_.render(); (<Blockly.BlockSvg>this.sourceBlock_).render();
this.sourceBlock_.bumpNeighbours_(); this.sourceBlock_.bumpNeighbours_();
} }
} }
@ -311,12 +311,12 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
// First dropdown // First dropdown
// Use one of the following options, medium motor, large motor or large motors (translated) // Use one of the following options, medium motor, large motor or large motors (translated)
const textNode1 = document.createTextNode(this.getFirstValueI11n(this.value_)); const textNode1 = document.createTextNode(this.getFirstValueI11n(<string>this.value_));
this.textElement_.appendChild(textNode1); this.textElement_.appendChild(textNode1);
// Second dropdown, no need to translate. Only port numbers // Second dropdown, no need to translate. Only port numbers
if (this.textElement2_) { if (this.textElement2_) {
const textNode2 = document.createTextNode(this.getSecondValue(this.value_)); const textNode2 = document.createTextNode(this.getSecondValue(<string>this.value_));
this.textElement2_.appendChild(textNode2); this.textElement2_.appendChild(textNode2);
} }
this.updateWidth(); this.updateWidth();
@ -401,7 +401,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
if (Blockly.DropDownDiv.hideIfOwner(this)) { if (Blockly.DropDownDiv.hideIfOwner(this)) {
return; return;
} }
this.isFirst_ = e.clientX - this.getScaledBBox_().left < ((this as any).width1 * this.sourceBlock_.workspace.scale); this.isFirst_ = e.clientX - this.getScaledBBox_().left < ((this as any).width1 * (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale);
// If there is an existing drop-down someone else owns, hide it immediately and clear it. // If there is an existing drop-down someone else owns, hide it immediately and clear it.
Blockly.DropDownDiv.hideWithoutAnimation(); Blockly.DropDownDiv.hideWithoutAnimation();
Blockly.DropDownDiv.clearContent(); Blockly.DropDownDiv.clearContent();
@ -433,8 +433,8 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
vals[text] = value; vals[text] = value;
} }
const currentFirst = this.getFirstValue(this.value_); const currentFirst = this.getFirstValue(<string>this.value_);
const currentSecond = this.getSecondValue(this.value_); const currentSecond = this.getSecondValue(<string>this.value_);
if (!this.isFirst_) { if (!this.isFirst_) {
options = opts[currentFirst]; options = opts[currentFirst];
@ -526,7 +526,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
Blockly.DropDownDiv.setColour(this.backgroundColour_, this.borderColour_); Blockly.DropDownDiv.setColour(this.backgroundColour_, this.borderColour_);
// Calculate positioning based on the field position. // Calculate positioning based on the field position.
let scale = this.sourceBlock_.workspace.scale; let scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
let width = this.isFirst_ ? (this as any).width1 : (this as any).width2; let width = this.isFirst_ ? (this as any).width1 : (this as any).width2;
let bBox = { width: this.size_.width, height: this.size_.height }; let bBox = { width: this.size_.width, height: this.size_.height };
width *= scale; width *= scale;
@ -538,7 +538,7 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
let secondaryX = primaryX; let secondaryX = primaryX;
let secondaryY = position.top; let secondaryY = position.top;
// Set bounds to workspace; show the drop-down. // Set bounds to workspace; show the drop-down.
(Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode); (Blockly.DropDownDiv as any).setBoundsElement((<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).getParentSvg().parentNode);
(Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY, (Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY,
this.onHide_.bind(this)); this.onHide_.bind(this));
@ -561,10 +561,11 @@ export class FieldMotors extends Blockly.FieldDropdown implements Blockly.FieldC
* Callback for when the drop-down is hidden. * Callback for when the drop-down is hidden.
*/ */
protected onHide_() { protected onHide_() {
Blockly.DropDownDiv.content_.removeAttribute('role'); const content = Blockly.DropDownDiv.getContentDiv();
Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup'); content.removeAttribute('role');
Blockly.DropDownDiv.content_.removeAttribute('aria-activedescendant'); content.removeAttribute('aria-haspopup');
Blockly.DropDownDiv.getContentDiv().style.width = ''; content.removeAttribute('aria-activedescendant');
content.style.width = '';
if (this.isFirst_ && this.box_) { if (this.isFirst_ && this.box_) {
this.box_.setAttribute('fill', this.sourceBlock_.getColour()); this.box_.setAttribute('fill', this.sourceBlock_.getColour());
} else if (!this.isFirst_ && this.box2_) { } else if (!this.isFirst_ && this.box2_) {

View File

@ -85,7 +85,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), this.sourceBlock_.getColourTertiary()); Blockly.DropDownDiv.setColour(this.sourceBlock_.getColour(), this.sourceBlock_.getColourTertiary());
// Calculate positioning based on the field position. // Calculate positioning based on the field position.
let scale = this.sourceBlock_.workspace.scale; let scale = (<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).scale;
let bBox = { width: this.size_.width, height: this.size_.height }; let bBox = { width: this.size_.width, height: this.size_.height };
bBox.width *= scale; bBox.width *= scale;
bBox.height *= scale; bBox.height *= scale;
@ -95,7 +95,7 @@ export class FieldMusic extends pxtblockly.FieldImages implements Blockly.FieldC
let secondaryX = primaryX; let secondaryX = primaryX;
let secondaryY = position.top; let secondaryY = position.top;
// Set bounds to workspace; show the drop-down. // Set bounds to workspace; show the drop-down.
(Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode); (Blockly.DropDownDiv as any).setBoundsElement((<Blockly.WorkspaceSvg>this.sourceBlock_.workspace).getParentSvg().parentNode);
(Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY, (Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY,
this.onHide_.bind(this)); this.onHide_.bind(this));

View File

@ -1,97 +0,0 @@
/// <reference path="../node_modules/pxt-core/localtypings/blockly.d.ts"/>
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
export interface FieldSpeedOptions extends Blockly.FieldCustomOptions {
min?: string;
max?: string;
label?: string;
}
export class FieldSpeed extends Blockly.FieldSlider implements Blockly.FieldCustom {
public isFieldCustom_ = true;
private params: any;
private speedSVG: SVGElement;
private circleBar: SVGCircleElement;
private reporter: SVGTextElement;
/**
* Class for a color wheel field.
* @param {number|string} value The initial content of the field.
* @param {Function=} opt_validator An optional function that is called
* to validate any constraints on what the user entered. Takes the new
* text as an argument and returns either the accepted text, a replacement
* text, or null to abort the change.
* @extends {Blockly.FieldNumber}
* @constructor
*/
constructor(value_: any, params: FieldSpeedOptions, opt_validator?: Function) {
super(String(value_), '-100', '100', null, '10', 'Speed', opt_validator);
this.params = params;
if (this.params['min']) this.min_ = parseFloat(this.params.min);
if (this.params['max']) this.max_ = parseFloat(this.params.max);
if (this.params['label']) this.labelText_ = this.params.label;
(this as any).sliderColor_ = '#a8aaa8';
}
createLabelDom_(labelText: string) {
var labelContainer = document.createElement('div');
this.speedSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg") as SVGGElement;
pxsim.svg.hydrate(this.speedSVG, {
viewBox: "0 0 200 100",
width: "170"
});
labelContainer.appendChild(this.speedSVG);
const outerCircle = pxsim.svg.child(this.speedSVG, "circle", {
'stroke-dasharray': '565.48', 'stroke-dashoffset': '0',
'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 0.1s linear;`,
'stroke': '#a8aaa8', 'stroke-width': '1rem'
}) as SVGCircleElement;
this.circleBar = pxsim.svg.child(this.speedSVG, "circle", {
'stroke-dasharray': '565.48', 'stroke-dashoffset': '0',
'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 0.1s linear;`,
'stroke': '#f12a21', 'stroke-width': '1rem'
}) as SVGCircleElement;
this.reporter = pxsim.svg.child(this.speedSVG, "text", {
'x': 100, 'y': 80,
'text-anchor': 'middle', 'dominant-baseline': 'middle',
'style': 'font-size: 50px',
'class': 'sim-text inverted number'
}) as SVGTextElement;
// labelContainer.setAttribute('class', 'blocklyFieldSliderLabel');
var readout = document.createElement('span');
readout.setAttribute('class', 'blocklyFieldSliderReadout');
// var label = document.createElement('span');
// label.setAttribute('class', 'blocklyFieldSliderLabelText');
// label.innerHTML = labelText;
// labelContainer.appendChild(label);
// labelContainer.appendChild(readout);
return [labelContainer, readout];
};
setReadout_(readout: Element, value: string) {
this.updateSpeed(parseFloat(value));
// Update reporter
this.reporter.textContent = `${value}%`;
}
private updateSpeed(speed: number) {
let sign = this.sign(speed);
speed = (Math.abs(speed) / 100 * 50) + 50;
if (sign == -1) speed = 50 - speed;
let c = Math.PI * (90 * 2);
let pct = ((100 - speed) / 100) * c;
this.circleBar.setAttribute('stroke-dashoffset', `${pct}`);
}
// A re-implementation of Math.sign (since IE11 doesn't support it)
private sign(num: number) {
return num ? num < 0 ? -1 : 1 : 0;
}
}

View File

@ -1,108 +0,0 @@
/// <reference path="../node_modules/pxt-core/localtypings/blockly.d.ts"/>
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
export interface FieldTurnRatioOptions extends Blockly.FieldCustomOptions {
}
export class FieldTurnRatio extends Blockly.FieldSlider implements Blockly.FieldCustom {
public isFieldCustom_ = true;
private params: any;
private path_: SVGPathElement;
private reporter_: SVGTextElement;
/**
* Class for a color wheel field.
* @param {number|string} value The initial content of the field.
* @param {Function=} opt_validator An optional function that is called
* to validate any constraints on what the user entered. Takes the new
* text as an argument and returns either the accepted text, a replacement
* text, or null to abort the change.
* @extends {Blockly.FieldNumber}
* @constructor
*/
constructor(value_: any, params: FieldTurnRatioOptions, opt_validator?: Function) {
super(String(value_), '-100', '100', null, '10', 'TurnRatio', opt_validator);
this.params = params;
(this as any).sliderColor_ = '#a8aaa8';
}
static HALF = 80;
static HANDLE_RADIUS = 30;
static RADIUS = FieldTurnRatio.HALF - FieldTurnRatio.HANDLE_RADIUS - 1;
createLabelDom_(labelText: string) {
let labelContainer = document.createElement('div');
let svg = Blockly.utils.createSvgElement('svg', {
'xmlns': 'http://www.w3.org/2000/svg',
'xmlns:html': 'http://www.w3.org/1999/xhtml',
'xmlns:xlink': 'http://www.w3.org/1999/xlink',
'version': '1.1',
'height': (FieldTurnRatio.HALF + FieldTurnRatio.HANDLE_RADIUS + 10) + 'px',
'width': (FieldTurnRatio.HALF * 2) + 'px'
}, labelContainer);
let defs = Blockly.utils.createSvgElement('defs', {}, svg);
let marker = Blockly.utils.createSvgElement('marker', {
'id': 'head',
'orient': "auto",
'markerWidth': '2',
'markerHeight': '4',
'refX': '0.1', 'refY': '1.5'
}, defs);
let markerPath = Blockly.utils.createSvgElement('path', {
'd': 'M0,0 V3 L1.5,1.5 Z',
'fill': '#f12a21'
}, marker);
this.reporter_ = pxsim.svg.child(svg, "text", {
'x': FieldTurnRatio.HALF, 'y': 96,
'text-anchor': 'middle', 'dominant-baseline': 'middle',
'style': 'font-size: 50px',
'class': 'sim-text inverted number'
}) as SVGTextElement;
this.path_ = Blockly.utils.createSvgElement('path', {
'x1': FieldTurnRatio.HALF,
'y1': FieldTurnRatio.HALF,
'marker-end': 'url(#head)',
'style': 'fill: none; stroke: #f12a21; stroke-width: 10'
}, svg);
this.updateGraph_();
let readout = document.createElement('span');
readout.setAttribute('class', 'blocklyFieldSliderReadout');
return [labelContainer, readout];
};
updateGraph_() {
if (!this.path_) {
return;
}
let v = goog.math.clamp(parseFloat(this.getText()), -100, 100);
if (isNaN(v)) {
v = 0;
}
const x = goog.math.clamp(parseFloat(this.getText()), -100, 100) / 100;
const theta = x * Math.PI / 2;
const cx = FieldTurnRatio.HALF;
const cy = FieldTurnRatio.HALF - 14;
const gamma = Math.PI - 2 * theta;
const r = FieldTurnRatio.RADIUS;
const alpha = 0.2 + Math.abs(x) * 0.5;
const x1 = 0;
const y1 = r * alpha;
const y2 = r * Math.sin(Math.PI / 2 - theta);
const x2 = r * Math.cos(Math.PI / 2 - theta);
const y3 = y2 - r * alpha * Math.cos(2 * theta);
const x3 = x2 - r * alpha * Math.sin(2 * theta);
const d = `M ${cx} ${cy} C ${cx} ${cy - y1} ${cx + x3} ${cy - y3} ${cx + x2} ${cy - y2}`;
this.path_.setAttribute('d', d);
this.reporter_.textContent = `${v}`;
}
setReadout_(readout: Element, value: string) {
this.updateGraph_();
}
}

View File

@ -22,13 +22,8 @@
} }
declare const enum ValType { declare const enum PerfCounters {
Undefined = 0, GC = 0,
Boolean = 1,
Number = 2,
String = 3,
Object = 4,
Function = 5,
} }
// Auto-generated. Do not edit. Really. // Auto-generated. Do not edit. Really.

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

@ -42,6 +42,12 @@ declare interface Buffer {
//% start.defl=0 length.defl=-1 shim=BufferMethods::shift //% start.defl=0 length.defl=-1 shim=BufferMethods::shift
shift(offset: int32, start?: int32, length?: int32): void; shift(offset: int32, start?: int32, length?: int32): void;
/**
* Convert a buffer to string assuming UTF8 encoding
*/
//% shim=BufferMethods::toString
toString(): string;
/** /**
* Convert a buffer to its hexadecimal representation. * Convert a buffer to its hexadecimal representation.
*/ */
@ -72,6 +78,13 @@ declare namespace control {
*/ */
//% shim=control::createBuffer //% shim=control::createBuffer
function createBuffer(size: int32): Buffer; 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
function createBufferFromUTF8(str: string): Buffer;
} }
declare namespace loops { declare namespace loops {
@ -147,7 +160,31 @@ declare namespace control {
* *
*/ */
//% shim=control::__log //% shim=control::__log
function __log(text: string): void; function __log(prority: int32, text: string): void;
/**
* Dump internal information about a value.
*/
//% shim=control::dmesgValue
function dmesgValue(v: any): void;
/**
* Force GC and dump basic information about heap.
*/
//% shim=control::gc
function gc(): void;
/**
* Force GC and halt waiting for debugger to do a full heap dump.
*/
//% shim=control::heapDump
function heapDump(): void;
/**
* Return true if profiling is enabled in the current build.
*/
//% shim=control::profilingEnabled
function profilingEnabled(): boolean;
} }
// Auto-generated. Do not edit. Really. // Auto-generated. Do not edit. Really.

View File

@ -749,9 +749,3 @@ namespace motors {
control.dmesg('end step') control.dmesg('end step')
} }
} }
interface Buffer {
[index: number]: number;
// rest defined in buffer.cpp
}

View File

@ -44,7 +44,7 @@ namespace console._screen {
printLog(); printLog();
} }
function log(msg: string): void { function log(priority: ConsolePriority, msg: string): void {
lines.push(msg); lines.push(msg);
if (lines.length + 5 > maxLines) { if (lines.length + 5 > maxLines) {
lines.splice(0, maxLines - lines.length); lines.splice(0, maxLines - lines.length);

View File

@ -45,6 +45,18 @@ declare interface Image {
//% shim=ImageMethods::fill //% shim=ImageMethods::fill
fill(c: int32): void; fill(c: int32): void;
/**
* Copy row(s) of pixel from image to buffer (8 bit per pixel).
*/
//% shim=ImageMethods::getRows
getRows(x: int32, dst: Buffer): void;
/**
* Copy row(s) of pixel from buffer to image.
*/
//% shim=ImageMethods::setRows
setRows(x: int32, src: Buffer): void;
/** /**
* Return a copy of the current image * Return a copy of the current image
*/ */

View File

@ -1,6 +1,6 @@
{ {
"name": "pxt-ev3", "name": "pxt-ev3",
"version": "1.0.11", "version": "1.1.0",
"description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode", "description": "LEGO MINDSTORMS EV3 for Microsoft MakeCode",
"private": true, "private": true,
"keywords": [ "keywords": [
@ -39,8 +39,8 @@
"webfonts-generator": "^0.4.0" "webfonts-generator": "^0.4.0"
}, },
"dependencies": { "dependencies": {
"pxt-common-packages": "0.23.56", "pxt-common-packages": "6.4.13",
"pxt-core": "4.0.9" "pxt-core": "5.5.18"
}, },
"scripts": { "scripts": {
"test": "node node_modules/pxt-core/built/pxt.js travis" "test": "node node_modules/pxt-core/built/pxt.js travis"

View File

@ -5,6 +5,7 @@
namespace pxsim { namespace pxsim {
export class EV3Board extends CoreBoard { export class EV3Board extends CoreBoard {
viewHost: visuals.BoardHost;
view: SVGSVGElement; view: SVGSVGElement;
outputState: EV3OutputState; outputState: EV3OutputState;
@ -83,15 +84,16 @@ namespace pxsim {
highContrast: msg.highContrast, highContrast: msg.highContrast,
light: msg.light light: msg.light
}; };
const viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView({ this.viewHost = new visuals.BoardHost(pxsim.visuals.mkBoardView(<pxsim.visuals.BoardViewOptions>{
visual: boardDef.visual, visual: boardDef.visual,
boardDef,
highContrast: msg.highContrast, highContrast: msg.highContrast,
light: msg.light light: msg.light
}), opts); }), opts);
document.body.innerHTML = ""; // clear children document.body.innerHTML = ""; // clear children
document.body.className = msg.light ? "light" : ""; document.body.className = msg.light ? "light" : "";
document.body.appendChild(this.view = viewHost.getView() as SVGSVGElement); document.body.appendChild(this.view = this.viewHost.getView() as SVGSVGElement);
this.inputNodes = []; this.inputNodes = [];
this.outputNodes = []; this.outputNodes = [];
@ -102,8 +104,8 @@ namespace pxsim {
return Promise.resolve(); return Promise.resolve();
} }
screenshot(): string { screenshotAsync(width?: number): Promise<ImageData> {
return svg.toDataUri(new XMLSerializer().serializeToString(this.view)); return this.viewHost.screenshotAsync(width);
} }
getBrickNode() { getBrickNode() {