Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
58763e398b | |||
f77bf165eb | |||
4880d9ea5b | |||
ab4fb019f9 | |||
2c2df31ba3 | |||
0f2bda2496 | |||
44386be3c7 | |||
89ca66b8a9 | |||
64389a7689 | |||
f77778ef85 | |||
7d01823caf | |||
b3f9a4c92f | |||
7fe8580de8 | |||
c70d6fe01a | |||
ed7099cc97 | |||
a79704fecc | |||
6a1b560101 | |||
5e21f9ab6d | |||
74648bd1df | |||
e24d4d56b1 | |||
ac428a3936 |
@ -4,6 +4,8 @@
|
|||||||
import { deployCoreAsync, initAsync } from "./deploy";
|
import { deployCoreAsync, initAsync } from "./deploy";
|
||||||
import { FieldPorts } from "./field_ports";
|
import { FieldPorts } from "./field_ports";
|
||||||
import { FieldImages } from "./field_images";
|
import { FieldImages } from "./field_images";
|
||||||
|
import {FieldSpeed} from "./field_speed";
|
||||||
|
import { FieldBrickButtons } from "./field_brickbuttons";
|
||||||
|
|
||||||
pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
|
pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): Promise<pxt.editor.ExtensionResult> {
|
||||||
pxt.debug('loading pxt-ev3 target extensions...')
|
pxt.debug('loading pxt-ev3 target extensions...')
|
||||||
@ -15,6 +17,12 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P
|
|||||||
}, {
|
}, {
|
||||||
selector: "images",
|
selector: "images",
|
||||||
editor: FieldImages
|
editor: FieldImages
|
||||||
|
}, {
|
||||||
|
selector: "speed",
|
||||||
|
editor: FieldSpeed
|
||||||
|
}, {
|
||||||
|
selector: "brickbuttons",
|
||||||
|
editor: FieldBrickButtons
|
||||||
}],
|
}],
|
||||||
deployCoreAsync
|
deployCoreAsync
|
||||||
};
|
};
|
||||||
|
159
editor/field_brickbuttons.ts
Normal file
159
editor/field_brickbuttons.ts
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
/// <reference path="../node_modules/pxt-core/localtypings/blockly.d.ts"/>
|
||||||
|
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
|
||||||
|
|
||||||
|
export interface FieldPortsOptions extends Blockly.FieldCustomDropdownOptions {
|
||||||
|
columns?: string;
|
||||||
|
width?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FieldBrickButtons extends Blockly.FieldDropdown implements Blockly.FieldCustom {
|
||||||
|
public isFieldCustom_ = true;
|
||||||
|
|
||||||
|
// Width in pixels
|
||||||
|
private width_: number;
|
||||||
|
|
||||||
|
// Columns in grid
|
||||||
|
private columns_: number;
|
||||||
|
|
||||||
|
private savedPrimary_: string;
|
||||||
|
|
||||||
|
constructor(text: string, options: FieldPortsOptions, validator?: Function) {
|
||||||
|
super(options.data);
|
||||||
|
|
||||||
|
this.columns_ = parseInt(options.columns) || 4;
|
||||||
|
this.width_ = parseInt(options.width) || 150;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a dropdown menu under the text.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
public showEditor_() {
|
||||||
|
// If there is an existing drop-down we own, this is a request to hide the drop-down.
|
||||||
|
if (Blockly.DropDownDiv.hideIfOwner(this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If there is an existing drop-down someone else owns, hide it immediately and clear it.
|
||||||
|
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||||
|
Blockly.DropDownDiv.clearContent();
|
||||||
|
// Populate the drop-down with the icons for this field.
|
||||||
|
let dropdownDiv = Blockly.DropDownDiv.getContentDiv();
|
||||||
|
let contentDiv = document.createElement('div');
|
||||||
|
// Accessibility properties
|
||||||
|
contentDiv.setAttribute('role', 'menu');
|
||||||
|
contentDiv.setAttribute('aria-haspopup', 'true');
|
||||||
|
|
||||||
|
const buttonsSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg") as SVGGElement;
|
||||||
|
pxsim.svg.hydrate(buttonsSVG, {
|
||||||
|
viewBox: "0 0 256.68237 256.68237",
|
||||||
|
width: this.width_,
|
||||||
|
height: this.width_
|
||||||
|
});
|
||||||
|
contentDiv.appendChild(buttonsSVG);
|
||||||
|
|
||||||
|
const gWrapper = pxsim.svg.child(buttonsSVG, 'g', { 'transform': 'translate(-4.695057,58.29823)' });
|
||||||
|
const gInnerWrapper = pxsim.svg.child(gWrapper, 'g', { 'transform': 'translate(3.9780427e-6,-32.677281)' });
|
||||||
|
|
||||||
|
const back = pxsim.svg.child(gInnerWrapper, 'path', {
|
||||||
|
style: 'fill:#6a6a6a;stroke-width:3.91719985',
|
||||||
|
d: 'M 106.30882,198.38022 C 84.431262,177.26258 50.453467,142.52878 50.453467,142.52878 v -7.12931 H 37.087971 a 32.381533,32.381533 0 1 1 0,-64.763062 H 50.457376 V 63.503186 L 105.71731,7.0563355 h 55.25604 c 25.02699,25.5048885 55.25994,55.2599395 55.25994,55.2599395 v 8.320133 h 12.77398 a 32.381533,32.381533 0 0 1 0,64.763062 h -12.77398 v 7.13323 c -29.43384,30.27603 -54.66454,55.85144 -54.66454,55.85144 z'
|
||||||
|
})
|
||||||
|
|
||||||
|
const buttonLeft = pxsim.svg.child(gInnerWrapper, 'path', {
|
||||||
|
style: 'fill:#a8a9a8;stroke-width:3.91719985',
|
||||||
|
d: 'm 36.492567,78.357208 h 40.69971 V 126.48393 H 36.492567 A 24.063359,24.063359 0 0 1 12.429199,102.42057 v 0 A 24.063359,24.063359 0 0 1 36.492567,78.357208 Z'
|
||||||
|
})
|
||||||
|
|
||||||
|
const buttonRight = pxsim.svg.child(gInnerWrapper, 'path', {
|
||||||
|
style: 'fill:#a8a9a8;stroke-width:3.91719985',
|
||||||
|
d: 'M 229.00727,126.48784 H 188.30756 V 78.361126 h 40.69971 a 24.063359,24.063359 0 0 1 24.06335,24.063354 v 0 a 24.063359,24.063359 0 0 1 -24.06335,24.06336 z'
|
||||||
|
})
|
||||||
|
|
||||||
|
const buttonEnter = pxsim.svg.child(gInnerWrapper, 'path', {
|
||||||
|
style: 'fill:#3c3c3c;stroke-width:3.91719985',
|
||||||
|
d: 'm 109.27806,78.357208 h 46.9398 a 1.782326,1.782326 0 0 1 1.78233,1.782326 V 124.7016 a 1.782326,1.782326 0 0 1 -1.78233,1.78233 h -46.9398 a 1.782326,1.782326 0 0 1 -1.78233,-1.78233 V 80.139534 a 1.782326,1.782326 0 0 1 1.78233,-1.782326 z'
|
||||||
|
})
|
||||||
|
|
||||||
|
const buttonTop = pxsim.svg.child(gInnerWrapper, 'path', {
|
||||||
|
style: 'fill:#a8a9a8;stroke-width:3.91719985',
|
||||||
|
d: 'm 108.09114,15.967966 49.90905,-0.59542 37.43276,38.619675 -15.44943,15.449437 V 97.367379 H 165.7249 V 81.306861 A 11.978797,11.978797 0 0 0 153.84012,69.422075 c -11.59883,-0.184102 -43.37516,0 -43.37516,0 A 9.6676495,9.6676495 0 0 0 100.36251,79.520618 V 97.347793 H 86.103905 V 69.422075 L 70.654464,53.97264 Z'
|
||||||
|
})
|
||||||
|
|
||||||
|
const buttonBottom = pxsim.svg.child(gInnerWrapper, 'path', {
|
||||||
|
style: 'fill:#a8a9a8;stroke-width:3.91719985',
|
||||||
|
d: 'M 157.78865,189.01028 108.18908,189.38233 70.654464,150.794 86.323259,135.4895 v -28.08625 h 14.101921 v 16.11144 a 12.006218,12.006218 0 0 0 11.85346,11.9788 c 11.59882,0.1841 43.13227,0 43.13227,0 a 10.18472,10.18472 0 0 0 10.38059,-10.38058 v -17.70966 h 14.39179 v 28.08632 l 15.3045,15.3045 z'
|
||||||
|
})
|
||||||
|
|
||||||
|
const buttons = [buttonEnter, buttonLeft, buttonRight, buttonTop, buttonBottom];
|
||||||
|
const options = this.getOptions();
|
||||||
|
for (let i = 0, option: any; option = options[i]; i++) {
|
||||||
|
let content = (options[i] as any)[0]; // Human-readable text or image.
|
||||||
|
const value = (options[i] as any)[1]; // Language-neutral value.
|
||||||
|
const button = buttons[i];
|
||||||
|
button.setAttribute('id', ':' + i); // For aria-activedescendant
|
||||||
|
button.setAttribute('role', 'menuitem');
|
||||||
|
button.setAttribute('cursor', 'pointer');
|
||||||
|
const title = pxsim.svg.child(button, 'title');
|
||||||
|
title.textContent = content;
|
||||||
|
|
||||||
|
Blockly.bindEvent_(button, 'click', this, this.buttonClick_);
|
||||||
|
Blockly.bindEvent_(button, 'mouseup', this, this.buttonClick_);
|
||||||
|
// These are applied manually instead of using the :hover pseudoclass
|
||||||
|
// because Android has a bad long press "helper" menu and green highlight
|
||||||
|
// that we must prevent with ontouchstart preventDefault
|
||||||
|
Blockly.bindEvent_(button, 'mousedown', button, function (e) {
|
||||||
|
this.setAttribute('stroke', '#ffffff');
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
Blockly.bindEvent_(button, 'mouseover', button, function () {
|
||||||
|
this.setAttribute('stroke', '#ffffff');
|
||||||
|
});
|
||||||
|
Blockly.bindEvent_(button, 'mouseout', button, function () {
|
||||||
|
this.setAttribute('stroke', 'transparent');
|
||||||
|
});
|
||||||
|
|
||||||
|
button.setAttribute('data-value', value);
|
||||||
|
}
|
||||||
|
|
||||||
|
contentDiv.style.width = this.width_ + 'px';
|
||||||
|
dropdownDiv.appendChild(contentDiv);
|
||||||
|
|
||||||
|
Blockly.DropDownDiv.setColour('#ffffff', '#dddddd');
|
||||||
|
|
||||||
|
// Calculate positioning based on the field position.
|
||||||
|
var scale = this.sourceBlock_.workspace.scale;
|
||||||
|
var bBox = { width: this.size_.width, height: this.size_.height };
|
||||||
|
bBox.width *= scale;
|
||||||
|
bBox.height *= scale;
|
||||||
|
var position = this.fieldGroup_.getBoundingClientRect();
|
||||||
|
var primaryX = position.left + bBox.width / 2;
|
||||||
|
var primaryY = position.top + bBox.height;
|
||||||
|
var secondaryX = primaryX;
|
||||||
|
var secondaryY = position.top;
|
||||||
|
// Set bounds to workspace; show the drop-down.
|
||||||
|
(Blockly.DropDownDiv as any).setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode);
|
||||||
|
(Blockly.DropDownDiv as any).show(this, primaryX, primaryY, secondaryX, secondaryY,
|
||||||
|
this.onHide_.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for when a button is clicked inside the drop-down.
|
||||||
|
* Should be bound to the FieldIconMenu.
|
||||||
|
* @param {Event} e DOM event for the click/touch
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
private buttonClick_ = function (e: any) {
|
||||||
|
let value = e.target.getAttribute('data-value');
|
||||||
|
this.setValue(value);
|
||||||
|
Blockly.DropDownDiv.hide();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback for when the drop-down is hidden.
|
||||||
|
*/
|
||||||
|
private onHide_ = function () {
|
||||||
|
Blockly.DropDownDiv.content_.removeAttribute('role');
|
||||||
|
Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup');
|
||||||
|
Blockly.DropDownDiv.content_.removeAttribute('aria-activedescendant');
|
||||||
|
};
|
||||||
|
}
|
96
editor/field_speed.ts
Normal file
96
editor/field_speed.ts
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/// <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"
|
||||||
|
});
|
||||||
|
|
||||||
|
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', 'alignment-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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"behaviors.addBehavior|block": "add behavior %behavior",
|
"behaviors.addBehavior|block": "add behavior %behavior",
|
||||||
"behaviors.avoidCrash|block": "avoid crash using %ultrasonic",
|
"behaviors.avoidCrash|block": "avoid crash using %ultrasonic",
|
||||||
"behaviors.driveForward|block": "drive %motors|forward at %speed|%",
|
"behaviors.driveForward|block": "drive %motors|forward at %speed=motorSpeedPicker|%",
|
||||||
"behaviors|block": "behaviors",
|
"behaviors|block": "behaviors",
|
||||||
"{id:category}Behaviors": "Behaviors"
|
"{id:category}Behaviors": "Behaviors"
|
||||||
}
|
}
|
@ -49,7 +49,7 @@ namespace behaviors {
|
|||||||
* @param motors
|
* @param motors
|
||||||
* @param speed the desired speed, eg: 50
|
* @param speed the desired speed, eg: 50
|
||||||
*/
|
*/
|
||||||
//% blockId=behaviorsDriveForward block="drive %motors|forward at %speed|%"
|
//% blockId=behaviorsDriveForward block="drive %motors|forward at %speed=motorSpeedPicker|%"
|
||||||
export function driveForward(motors: motors.MotorBase, speed: number): behaviors.Behavior {
|
export function driveForward(motors: motors.MotorBase, speed: number): behaviors.Behavior {
|
||||||
return new DriveForwardBehavior(motors, speed);
|
return new DriveForwardBehavior(motors, speed);
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
"sensors.ColorSensor.onColorDetected|block": "on %sensor|detected color %color",
|
"sensors.ColorSensor.onColorDetected|block": "on %sensor|detected color %color",
|
||||||
"sensors.ColorSensor.onLightChanged|block": "on %sensor|%mode|%condition",
|
"sensors.ColorSensor.onLightChanged|block": "on %sensor|%mode|%condition",
|
||||||
"sensors.ColorSensor.pauseForColor|block": "pause %sensor|for color %color",
|
"sensors.ColorSensor.pauseForColor|block": "pause %sensor|for color %color",
|
||||||
"sensors.ColorSensor.pauseForLight|block": "pause %sensor|for %mode|light %condition",
|
"sensors.ColorSensor.pauseForLight|block": "pause %sensor|for %mode|%condition",
|
||||||
"sensors.color1|block": "color 1",
|
"sensors.color1|block": "color 1",
|
||||||
"sensors.color2|block": "color 2",
|
"sensors.color2|block": "color 2",
|
||||||
"sensors.color3|block": "color 3",
|
"sensors.color3|block": "color 3",
|
||||||
|
@ -182,7 +182,7 @@ namespace sensors {
|
|||||||
* @param color the color to detect
|
* @param color the color to detect
|
||||||
*/
|
*/
|
||||||
//% help=sensors/color-sensor/pause-for-light
|
//% help=sensors/color-sensor/pause-for-light
|
||||||
//% block="pause %sensor|for %mode|light %condition"
|
//% block="pause %sensor|for %mode|%condition"
|
||||||
//% blockId=colorPauseForLight
|
//% blockId=colorPauseForLight
|
||||||
//% parts="colorsensor"
|
//% parts="colorsensor"
|
||||||
//% blockNamespace=sensors
|
//% blockNamespace=sensors
|
||||||
|
@ -30,14 +30,20 @@
|
|||||||
"brick.clearScreen": "Clears the screen",
|
"brick.clearScreen": "Clears the screen",
|
||||||
"brick.lightPattern": "Pattern block.",
|
"brick.lightPattern": "Pattern block.",
|
||||||
"brick.lightPattern|param|pattern": "the lights pattern to use. eg: LightsPattern.Green",
|
"brick.lightPattern|param|pattern": "the lights pattern to use. eg: LightsPattern.Green",
|
||||||
"brick.printLine": "Show text on the screen at a specific line.",
|
|
||||||
"brick.printLine|param|line": "the line number to print the text at, eg: 0",
|
|
||||||
"brick.printLine|param|text": "the text to print on the screen, eg: \"Hello world\"",
|
|
||||||
"brick.printPorts": "Prints the port states on the screen",
|
"brick.printPorts": "Prints the port states on the screen",
|
||||||
"brick.setLight": "Set lights.",
|
"brick.setLight": "Set lights.",
|
||||||
"brick.setLight|param|pattern": "the lights pattern to use.",
|
"brick.setLight|param|pattern": "the lights pattern to use.",
|
||||||
"brick.showImage": "Shows an image on screen",
|
"brick.showImage": "Shows an image on screen",
|
||||||
"brick.showImage|param|image": "image to draw",
|
"brick.showImage|param|image": "image to draw",
|
||||||
|
"brick.showNumber": "Shows a number on the screen",
|
||||||
|
"brick.showNumber|param|line": "the line number to print the text at, eg: 1",
|
||||||
|
"brick.showNumber|param|value": "the numeric value",
|
||||||
|
"brick.showString": "Show text on the screen at a specific line.",
|
||||||
|
"brick.showString|param|line": "the line number to print the text at, eg: 1",
|
||||||
|
"brick.showString|param|text": "the text to print on the screen, eg: \"Hello world\"",
|
||||||
|
"brick.showValue": "Shows a name, value pair on the screen",
|
||||||
|
"brick.showValue|param|line": "the line number to print the text at, eg: 1",
|
||||||
|
"brick.showValue|param|value": "the numeric value",
|
||||||
"console": "Reading and writing data to the console output.\n\nReading and writing data to the console output.",
|
"console": "Reading and writing data to the console output.\n\nReading and writing data to the console output.",
|
||||||
"console.addListener": "Adds a listener for the log messages",
|
"console.addListener": "Adds a listener for the log messages",
|
||||||
"console.log": "Write a line of text to the console output.",
|
"console.log": "Write a line of text to the console output.",
|
||||||
|
@ -37,10 +37,12 @@
|
|||||||
"brick.buttonUp|block": "up",
|
"brick.buttonUp|block": "up",
|
||||||
"brick.clearScreen|block": "clear screen",
|
"brick.clearScreen|block": "clear screen",
|
||||||
"brick.lightPattern|block": "%pattern",
|
"brick.lightPattern|block": "%pattern",
|
||||||
"brick.printLine|block": "print %text| at line %line",
|
|
||||||
"brick.printPorts|block": "print ports",
|
"brick.printPorts|block": "print ports",
|
||||||
"brick.setLight|block": "set light to %pattern=led_pattern",
|
"brick.setLight|block": "set light to %pattern=led_pattern",
|
||||||
"brick.showImage|block": "show image %image=screen_image_picker",
|
"brick.showImage|block": "show image %image=screen_image_picker",
|
||||||
|
"brick.showNumber|block": "show number %name|at line %line",
|
||||||
|
"brick.showString|block": "show string %text|at line %line",
|
||||||
|
"brick.showValue|block": "show value %name|= %text|at line %line",
|
||||||
"brick|block": "brick",
|
"brick|block": "brick",
|
||||||
"console.logValue|block": "console|log value %name|= %value",
|
"console.logValue|block": "console|log value %name|= %value",
|
||||||
"console.log|block": "console|log %text",
|
"console.log|block": "console|log %text",
|
||||||
@ -55,12 +57,12 @@
|
|||||||
"motors.MotorBase.pauseUntilReady|block": "%motor|pause until ready",
|
"motors.MotorBase.pauseUntilReady|block": "%motor|pause until ready",
|
||||||
"motors.MotorBase.setBrake|block": "set %motor|brake %brake",
|
"motors.MotorBase.setBrake|block": "set %motor|brake %brake",
|
||||||
"motors.MotorBase.setReversed|block": "set %motor|reversed %reversed",
|
"motors.MotorBase.setReversed|block": "set %motor|reversed %reversed",
|
||||||
"motors.MotorBase.setSpeedFor|block": "set %motor|speed to %speed|%|for %value|%unit",
|
"motors.MotorBase.setSpeedFor|block": "set %motor|speed to %speed=motorSpeedPicker|%|for %value|%unit",
|
||||||
"motors.MotorBase.setSpeed|block": "set %motor|speed to %speed|%",
|
"motors.MotorBase.setSpeed|block": "set %motor|speed to %speed=motorSpeedPicker|%",
|
||||||
"motors.SynchedMotorPair.steerFor|block": "steer %chassis|turn ratio %turnRatio|speed %speed|%|for %value|%unit",
|
"motors.SynchedMotorPair.steerFor|block": "steer %chassis|turn ratio %turnRatio|speed %speed=motorSpeedPicker|%|for %value|%unit",
|
||||||
"motors.SynchedMotorPair.steer|block": "steer %chassis|turn ratio %turnRatio|speed %speed|%",
|
"motors.SynchedMotorPair.steer|block": "steer %chassis|turn ratio %turnRatio|speed %speed=motorSpeedPicker|%",
|
||||||
"motors.SynchedMotorPair.tankFor|block": "tank %motors|%speedLeft|%|%speedRight|%|for %value|%unit",
|
"motors.SynchedMotorPair.tankFor|block": "tank %motors|%speedLeft=motorSpeedPicker|%|%speedRight=motorSpeedPicker|%|for %value|%unit",
|
||||||
"motors.SynchedMotorPair.tank|block": "tank %motors|%speedLeft|%|%speedRight|%",
|
"motors.SynchedMotorPair.tank|block": "tank %motors|%speedLeft=motorSpeedPicker|%|%speedRight=motorSpeedPicker|%",
|
||||||
"motors.largeAB|block": "large A+B",
|
"motors.largeAB|block": "large A+B",
|
||||||
"motors.largeAD|block": "large A+D",
|
"motors.largeAD|block": "large A+D",
|
||||||
"motors.largeA|block": "large A",
|
"motors.largeA|block": "large A",
|
||||||
@ -92,9 +94,9 @@
|
|||||||
"{id:group}Buttons": "Buttons",
|
"{id:group}Buttons": "Buttons",
|
||||||
"{id:group}Counters": "Counters",
|
"{id:group}Counters": "Counters",
|
||||||
"{id:group}Light": "Light",
|
"{id:group}Light": "Light",
|
||||||
|
"{id:group}Measured Move": "Measured Move",
|
||||||
"{id:group}More": "More",
|
"{id:group}More": "More",
|
||||||
"{id:group}Motion": "Motion",
|
"{id:group}Move": "Move",
|
||||||
"{id:group}Screen": "Screen",
|
"{id:group}Screen": "Screen",
|
||||||
"{id:group}Sensors": "Sensors",
|
"{id:group}Sensors": "Sensors"
|
||||||
"{id:group}Sync Motion": "Sync Motion"
|
|
||||||
}
|
}
|
@ -92,6 +92,7 @@ namespace brick {
|
|||||||
//% blockNamespace=brick
|
//% blockNamespace=brick
|
||||||
//% weight=81 blockGap=8
|
//% weight=81 blockGap=8
|
||||||
//% group="Buttons"
|
//% group="Buttons"
|
||||||
|
//% button.fieldEditor="brickbuttons"
|
||||||
isPressed() {
|
isPressed() {
|
||||||
return this._isPressed
|
return this._isPressed
|
||||||
}
|
}
|
||||||
@ -107,6 +108,7 @@ namespace brick {
|
|||||||
//% blockNamespace=brick
|
//% blockNamespace=brick
|
||||||
//% weight=80
|
//% weight=80
|
||||||
//% group="Buttons"
|
//% group="Buttons"
|
||||||
|
//% button.fieldEditor="brickbuttons"
|
||||||
wasPressed() {
|
wasPressed() {
|
||||||
const r = this._wasPressed
|
const r = this._wasPressed
|
||||||
this._wasPressed = false
|
this._wasPressed = false
|
||||||
@ -125,6 +127,7 @@ namespace brick {
|
|||||||
//% blockNamespace=brick
|
//% blockNamespace=brick
|
||||||
//% weight=99 blockGap=8
|
//% weight=99 blockGap=8
|
||||||
//% group="Buttons"
|
//% group="Buttons"
|
||||||
|
//% button.fieldEditor="brickbuttons"
|
||||||
onEvent(ev: ButtonEvent, body: () => void) {
|
onEvent(ev: ButtonEvent, body: () => void) {
|
||||||
control.onEvent(this._id, ev, body)
|
control.onEvent(this._id, ev, body)
|
||||||
}
|
}
|
||||||
@ -139,6 +142,7 @@ namespace brick {
|
|||||||
//% blockNamespace=brick
|
//% blockNamespace=brick
|
||||||
//% weight=98 blockGap=8
|
//% weight=98 blockGap=8
|
||||||
//% group="Buttons"
|
//% group="Buttons"
|
||||||
|
//% button.fieldEditor="brickbuttons"
|
||||||
pauseUntil(ev: ButtonEvent) {
|
pauseUntil(ev: ButtonEvent) {
|
||||||
control.waitForEvent(this._id, ev);
|
control.waitForEvent(this._id, ev);
|
||||||
}
|
}
|
||||||
@ -166,7 +170,6 @@ namespace brick {
|
|||||||
// this needs to be done in query(), which is run without the main JS execution mutex
|
// this needs to be done in query(), which is run without the main JS execution mutex
|
||||||
// otherwise, while(true){} will lock the device
|
// otherwise, while(true){} will lock the device
|
||||||
if (ret & DAL.BUTTON_ID_ESCAPE) {
|
if (ret & DAL.BUTTON_ID_ESCAPE) {
|
||||||
motors.stopAllMotors();
|
|
||||||
control.reset()
|
control.reset()
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
@ -483,7 +483,15 @@ void runLMS() {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stopMotors() {
|
||||||
|
uint8_t cmd[2] = { 0xA3, 0x0F };
|
||||||
|
int fd = open("/dev/lms_pwm", O_RDWR);
|
||||||
|
write(fd, cmd, 2);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void target_reset() {
|
extern "C" void target_reset() {
|
||||||
|
stopMotors();
|
||||||
if (lmsPid)
|
if (lmsPid)
|
||||||
runLMS();
|
runLMS();
|
||||||
else
|
else
|
||||||
|
@ -1 +1,14 @@
|
|||||||
|
|
||||||
|
namespace motors {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A speed picker
|
||||||
|
* @param speed the speed, eg: 50
|
||||||
|
*/
|
||||||
|
//% blockId=motorSpeedPicker block="%speed" shim=TD_ID
|
||||||
|
//% speed.fieldEditor="speed" colorSecondary="#FFFFFF"
|
||||||
|
//% weight=0 blockHidden=1 speed.fieldOptions.decompileLiterals=1
|
||||||
|
export function __speedPicker(speed: number): number {
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
}
|
@ -112,7 +112,7 @@ namespace motors {
|
|||||||
*/
|
*/
|
||||||
//% blockId=motorStopAll block="stop all motors"
|
//% blockId=motorStopAll block="stop all motors"
|
||||||
//% weight=5
|
//% weight=5
|
||||||
//% group="Motion"
|
//% group="Move"
|
||||||
export function stopAllMotors() {
|
export function stopAllMotors() {
|
||||||
const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
|
const b = mkCmd(Output.ALL, DAL.opOutputStop, 0)
|
||||||
writePWM(b)
|
writePWM(b)
|
||||||
@ -121,7 +121,7 @@ namespace motors {
|
|||||||
/**
|
/**
|
||||||
* Resets all motors
|
* Resets all motors
|
||||||
*/
|
*/
|
||||||
//% group="Motion"
|
//% group="Move"
|
||||||
export function resetAllMotors() {
|
export function resetAllMotors() {
|
||||||
reset(Output.ALL)
|
reset(Output.ALL)
|
||||||
}
|
}
|
||||||
@ -164,7 +164,7 @@ namespace motors {
|
|||||||
//% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake"
|
//% blockId=outputMotorSetBrakeMode block="set %motor|brake %brake"
|
||||||
//% brake.fieldEditor=toggleonoff
|
//% brake.fieldEditor=toggleonoff
|
||||||
//% weight=60 blockGap=8
|
//% weight=60 blockGap=8
|
||||||
//% group="Motion"
|
//% group="Move"
|
||||||
setBrake(brake: boolean) {
|
setBrake(brake: boolean) {
|
||||||
this.init();
|
this.init();
|
||||||
this._brake = brake;
|
this._brake = brake;
|
||||||
@ -176,7 +176,7 @@ namespace motors {
|
|||||||
//% blockId=motorSetReversed block="set %motor|reversed %reversed"
|
//% blockId=motorSetReversed block="set %motor|reversed %reversed"
|
||||||
//% reversed.fieldEditor=toggleonoff
|
//% reversed.fieldEditor=toggleonoff
|
||||||
//% weight=59
|
//% weight=59
|
||||||
//% group="Motion"
|
//% group="Move"
|
||||||
setReversed(reversed: boolean) {
|
setReversed(reversed: boolean) {
|
||||||
this.init();
|
this.init();
|
||||||
const b = mkCmd(this._port, DAL.opOutputPolarity, 1)
|
const b = mkCmd(this._port, DAL.opOutputPolarity, 1)
|
||||||
@ -206,11 +206,10 @@ namespace motors {
|
|||||||
* Sets the speed of the motor.
|
* Sets the speed of the motor.
|
||||||
* @param speed the speed from ``100`` full forward to ``-100`` full backward, eg: 50
|
* @param speed the speed from ``100`` full forward to ``-100`` full backward, eg: 50
|
||||||
*/
|
*/
|
||||||
//% blockId=motorSetSpeed block="set %motor|speed to %speed|%"
|
//% blockId=motorSetSpeed block="set %motor|speed to %speed=motorSpeedPicker|%"
|
||||||
//% on.fieldEditor=toggleonoff
|
//% on.fieldEditor=toggleonoff
|
||||||
//% weight=99 blockGap=8
|
//% weight=99 blockGap=8
|
||||||
//% speed.min=-100 speed.max=100
|
//% group="Move"
|
||||||
//% group="Motion"
|
|
||||||
setSpeed(speed: number) {
|
setSpeed(speed: number) {
|
||||||
this.init();
|
this.init();
|
||||||
speed = Math.clamp(-100, 100, speed >> 0);
|
speed = Math.clamp(-100, 100, speed >> 0);
|
||||||
@ -226,10 +225,9 @@ namespace motors {
|
|||||||
* @param value the move quantity, eg: 2
|
* @param value the move quantity, eg: 2
|
||||||
* @param unit the meaning of the value
|
* @param unit the meaning of the value
|
||||||
*/
|
*/
|
||||||
//% blockId=motorMove block="set %motor|speed to %speed|%|for %value|%unit"
|
//% blockId=motorMove block="set %motor|speed to %speed=motorSpeedPicker|%|for %value|%unit"
|
||||||
//% weight=98 blockGap=8
|
//% weight=98 blockGap=8
|
||||||
//% speed.min=-100 speed.max=100
|
//% group="Measured Move"
|
||||||
//% group="Motion"
|
|
||||||
setSpeedFor(speed: number, value: number, unit: MoveUnit) {
|
setSpeedFor(speed: number, value: number, unit: MoveUnit) {
|
||||||
this.init();
|
this.init();
|
||||||
speed = Math.clamp(-100, 100, speed >> 0);
|
speed = Math.clamp(-100, 100, speed >> 0);
|
||||||
@ -278,8 +276,8 @@ namespace motors {
|
|||||||
* @param timeOut optional maximum pausing time in milliseconds
|
* @param timeOut optional maximum pausing time in milliseconds
|
||||||
*/
|
*/
|
||||||
//% blockId=motorPauseUntilRead block="%motor|pause until ready"
|
//% blockId=motorPauseUntilRead block="%motor|pause until ready"
|
||||||
//% weight=97
|
//% weight=90
|
||||||
//% group="Motion"
|
//% group="Move"
|
||||||
pauseUntilReady(timeOut?: number) {
|
pauseUntilReady(timeOut?: number) {
|
||||||
pauseUntil(() => this.isReady(), timeOut);
|
pauseUntil(() => this.isReady(), timeOut);
|
||||||
}
|
}
|
||||||
@ -467,9 +465,9 @@ namespace motors {
|
|||||||
* @param speedLeft the speed on the left motor, eg: 50
|
* @param speedLeft the speed on the left motor, eg: 50
|
||||||
* @param speedRight the speed on the right motor, eg: 50
|
* @param speedRight the speed on the right motor, eg: 50
|
||||||
*/
|
*/
|
||||||
//% blockId=motorPairTank block="tank %motors|%speedLeft|%|%speedRight|%"
|
//% blockId=motorPairTank block="tank %motors|%speedLeft=motorSpeedPicker|%|%speedRight=motorSpeedPicker|%"
|
||||||
//% weight=20 blockGap=8
|
//% weight=96 blockGap=8
|
||||||
//% group="Sync Motion"
|
//% group="Move"
|
||||||
tank(speedLeft: number, speedRight: number) {
|
tank(speedLeft: number, speedRight: number) {
|
||||||
this.tankFor(speedLeft, speedRight, 0, MoveUnit.Degrees);
|
this.tankFor(speedLeft, speedRight, 0, MoveUnit.Degrees);
|
||||||
}
|
}
|
||||||
@ -485,12 +483,10 @@ namespace motors {
|
|||||||
* @param value the amount of movement, eg: 2
|
* @param value the amount of movement, eg: 2
|
||||||
* @param unit the unit of the value
|
* @param unit the unit of the value
|
||||||
*/
|
*/
|
||||||
//% blockId=motorPairTankFor block="tank %motors|%speedLeft|%|%speedRight|%|for %value|%unit"
|
//% blockId=motorPairTankFor block="tank %motors|%speedLeft=motorSpeedPicker|%|%speedRight=motorSpeedPicker|%|for %value|%unit"
|
||||||
//% weight=19
|
//% weight=19 blockGap=8
|
||||||
//% speedLeft.min=-100 speedLeft=100
|
|
||||||
//% speedRight.min=-100 speedRight=100
|
|
||||||
//% inlineInputMode=inline
|
//% inlineInputMode=inline
|
||||||
//% group="Sync Motion"
|
//% group="Measured Move"
|
||||||
tankFor(speedLeft: number, speedRight: number, value: number, unit: MoveUnit) {
|
tankFor(speedLeft: number, speedRight: number, value: number, unit: MoveUnit) {
|
||||||
this.init();
|
this.init();
|
||||||
|
|
||||||
@ -513,13 +509,13 @@ namespace motors {
|
|||||||
* @param value the move quantity, eg: 2
|
* @param value the move quantity, eg: 2
|
||||||
* @param unit the meaning of the value
|
* @param unit the meaning of the value
|
||||||
*/
|
*/
|
||||||
//% blockId=motorPairSteer block="steer %chassis|turn ratio %turnRatio|speed %speed|%"
|
//% blockId=motorPairSteer block="steer %chassis|turn ratio %turnRatio|speed %speed=motorSpeedPicker|%"
|
||||||
//% weight=7 blockGap=8
|
//% weight=95
|
||||||
//% turnRatio.min=-200 turnRatio=200
|
//% turnRatio.min=-200 turnRatio=200
|
||||||
//% inlineInputMode=inline
|
//% inlineInputMode=inline
|
||||||
//% group="Sync Motion"
|
//% group="Move"
|
||||||
steer(turnRatio: number, speed: number) {
|
steer(turnRatio: number, speed: number) {
|
||||||
this.steer(turnRatio, speed);
|
this.steerFor(turnRatio, speed, 0, MoveUnit.Rotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -529,11 +525,11 @@ namespace motors {
|
|||||||
* @param value the move quantity, eg: 2
|
* @param value the move quantity, eg: 2
|
||||||
* @param unit the meaning of the value
|
* @param unit the meaning of the value
|
||||||
*/
|
*/
|
||||||
//% blockId=motorPairSteerFor block="steer %chassis|turn ratio %turnRatio|speed %speed|%|for %value|%unit"
|
//% blockId=motorPairSteerFor block="steer %chassis|turn ratio %turnRatio|speed %speed=motorSpeedPicker|%|for %value|%unit"
|
||||||
//% weight=6 blockGap=8
|
//% weight=6
|
||||||
//% turnRatio.min=-200 turnRatio=200
|
//% turnRatio.min=-200 turnRatio=200
|
||||||
//% inlineInputMode=inline
|
//% inlineInputMode=inline
|
||||||
//% group="Sync Motion"
|
//% group="Measured Move"
|
||||||
steerFor(turnRatio: number, speed: number, value: number, unit: MoveUnit) {
|
steerFor(turnRatio: number, speed: number, value: number, unit: MoveUnit) {
|
||||||
this.init();
|
this.init();
|
||||||
speed = Math.clamp(-100, 100, speed >> 0);
|
speed = Math.clamp(-100, 100, speed >> 0);
|
||||||
|
@ -90,18 +90,42 @@ namespace brick {
|
|||||||
/**
|
/**
|
||||||
* Show text on the screen at a specific line.
|
* Show text on the screen at a specific line.
|
||||||
* @param text the text to print on the screen, eg: "Hello world"
|
* @param text the text to print on the screen, eg: "Hello world"
|
||||||
* @param line the line number to print the text at, eg: 0
|
* @param line the line number to print the text at, eg: 1
|
||||||
*/
|
*/
|
||||||
//% blockId=screen_print block="print %text| at line %line"
|
//% blockId=screen_print block="show string %text|at line %line"
|
||||||
//% weight=98 group="Screen" inlineInputMode="inline" blockGap=8
|
//% weight=98 group="Screen" inlineInputMode="inline" blockGap=8
|
||||||
//% line.min=0 line.max=9
|
//% line.min=1 line.max=10
|
||||||
export function printLine(text: string, line: number) {
|
export function showString(text: string, line: number) {
|
||||||
const NUM_LINES = 9;
|
const NUM_LINES = 9;
|
||||||
const offset = 5;
|
const offset = 5;
|
||||||
const y = offset + (Math.clamp(0, NUM_LINES, line) / (NUM_LINES + 2)) * DAL.LCD_HEIGHT;
|
const y = offset + (Math.clamp(0, NUM_LINES, line - 1) / (NUM_LINES + 2)) * DAL.LCD_HEIGHT;
|
||||||
brick.print(text, offset, y);
|
brick.print(text, offset, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows 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
|
||||||
|
//% line.min=1 line.max=10
|
||||||
|
export function showNumber(value: number, line: number) {
|
||||||
|
showString("" + value, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a name, value pair on the screen
|
||||||
|
* @param value the numeric value
|
||||||
|
* @param line the line number to print the text at, eg: 1
|
||||||
|
*/
|
||||||
|
//% blockId=screenShowValue block="show value %name|= %text|at line %line"
|
||||||
|
//% weight=96 group="Screen" inlineInputMode="inline" blockGap=8
|
||||||
|
//% line.min=1 line.max=10
|
||||||
|
export function showValue(name: string, value: number, line: number) {
|
||||||
|
showString((name ? name + ": " : "") + value, line);
|
||||||
|
}
|
||||||
|
|
||||||
export function print(text: string, x: number, y: number, mode = Draw.Normal) {
|
export function print(text: string, x: number, y: number, mode = Draw.Normal) {
|
||||||
x |= 0
|
x |= 0
|
||||||
y |= 0
|
y |= 0
|
||||||
@ -223,9 +247,6 @@ namespace brick {
|
|||||||
const x = i * 52;
|
const x = i * 52;
|
||||||
print(`${data.actualSpeed}%`, x, brick.LINE_HEIGHT)
|
print(`${data.actualSpeed}%`, x, brick.LINE_HEIGHT)
|
||||||
print(`${data.count}>`, x, 2 * brick.LINE_HEIGHT)
|
print(`${data.count}>`, x, 2 * brick.LINE_HEIGHT)
|
||||||
|
|
||||||
console.logValue(`speed.` + "ABCD"[i], data.actualSpeed);
|
|
||||||
console.logValue(`angle.` + "ABCD"[i], data.count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sensors
|
// sensors
|
||||||
@ -235,8 +256,6 @@ namespace brick {
|
|||||||
const x = (si.port() - 1) * 52;
|
const x = (si.port() - 1) * 52;
|
||||||
const v = si._query();
|
const v = si._query();
|
||||||
print(`${v}`, x, 9 * brick.LINE_HEIGHT)
|
print(`${v}`, x, 9 * brick.LINE_HEIGHT)
|
||||||
|
|
||||||
console.logValue(`sensor.` + si.port(), v);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ namespace sensors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//% color="#A5CA18" weight=90 icon="\uf10d"
|
//% color="#A5CA18" weight=90 icon="\uf10d"
|
||||||
//% groups='["Motion", "Counters", "Sync Motion"]'
|
//% groups='["Move", "Counters", "Measured Move"]'
|
||||||
//% labelLineWidth=0
|
//% labelLineWidth=0
|
||||||
namespace motors {
|
namespace motors {
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pxt-ev3",
|
"name": "pxt-ev3",
|
||||||
"version": "0.0.55",
|
"version": "0.0.56",
|
||||||
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
|
"description": "LEGO Mindstorms EV3 for Microsoft MakeCode",
|
||||||
"private": true,
|
"private": true,
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
@ -74,6 +74,19 @@ span.blocklyTreeLabel {
|
|||||||
border-radius: 0px !important;
|
border-radius: 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blocklyDropDownArrow.arrowTop {
|
||||||
|
border-top-left-radius: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocklyToggleRect {
|
||||||
|
rx: 0 !important;
|
||||||
|
ry: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.blocklyDropDownButton {
|
||||||
|
border-radius: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
/* Mobile */
|
/* Mobile */
|
||||||
@media only screen and (max-width: @largestMobileScreen) {
|
@media only screen and (max-width: @largestMobileScreen) {
|
||||||
#blocklyTrashIcon {
|
#blocklyTrashIcon {
|
||||||
|
Reference in New Issue
Block a user