Merge pull request #201 from Microsoft/speedfield
Add a speed field editor
This commit is contained in:
commit
89ca66b8a9
@ -4,6 +4,7 @@
|
|||||||
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";
|
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> {
|
||||||
@ -16,6 +17,9 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P
|
|||||||
}, {
|
}, {
|
||||||
selector: "images",
|
selector: "images",
|
||||||
editor: FieldImages
|
editor: FieldImages
|
||||||
|
}, {
|
||||||
|
selector: "speed",
|
||||||
|
editor: FieldSpeed
|
||||||
}, {
|
}, {
|
||||||
selector: "brickbuttons",
|
selector: "brickbuttons",
|
||||||
editor: FieldBrickButtons
|
editor: FieldBrickButtons
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -55,12 +55,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",
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -206,10 +206,9 @@ 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="Motion"
|
//% group="Motion"
|
||||||
setSpeed(speed: number) {
|
setSpeed(speed: number) {
|
||||||
this.init();
|
this.init();
|
||||||
@ -226,9 +225,8 @@ 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="Motion"
|
//% group="Motion"
|
||||||
setSpeedFor(speed: number, value: number, unit: MoveUnit) {
|
setSpeedFor(speed: number, value: number, unit: MoveUnit) {
|
||||||
this.init();
|
this.init();
|
||||||
@ -467,7 +465,7 @@ 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=20 blockGap=8
|
||||||
//% group="Sync Motion"
|
//% group="Sync Motion"
|
||||||
tank(speedLeft: number, speedRight: number) {
|
tank(speedLeft: number, speedRight: number) {
|
||||||
@ -485,7 +483,7 @@ 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
|
||||||
//% speedLeft.min=-100 speedLeft=100
|
//% speedLeft.min=-100 speedLeft=100
|
||||||
//% speedRight.min=-100 speedRight=100
|
//% speedRight.min=-100 speedRight=100
|
||||||
@ -513,7 +511,7 @@ 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=7 blockGap=8
|
||||||
//% turnRatio.min=-200 turnRatio=200
|
//% turnRatio.min=-200 turnRatio=200
|
||||||
//% inlineInputMode=inline
|
//% inlineInputMode=inline
|
||||||
@ -529,7 +527,7 @@ 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 blockGap=8
|
||||||
//% turnRatio.min=-200 turnRatio=200
|
//% turnRatio.min=-200 turnRatio=200
|
||||||
//% inlineInputMode=inline
|
//% inlineInputMode=inline
|
||||||
|
Loading…
Reference in New Issue
Block a user