Add a speed field editor
This commit is contained in:
		@@ -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";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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 +16,9 @@ pxt.editor.initExtensionsAsync = function (opts: pxt.editor.ExtensionOptions): P
 | 
				
			|||||||
        }, {
 | 
					        }, {
 | 
				
			||||||
            selector: "images",
 | 
					            selector: "images",
 | 
				
			||||||
            editor: FieldImages
 | 
					            editor: FieldImages
 | 
				
			||||||
 | 
					        }, {
 | 
				
			||||||
 | 
					            selector: "speed",
 | 
				
			||||||
 | 
					            editor: FieldSpeed
 | 
				
			||||||
        }],
 | 
					        }],
 | 
				
			||||||
        deployCoreAsync
 | 
					        deployCoreAsync
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										92
									
								
								editor/field_speed.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								editor/field_speed.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					/// <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) {
 | 
				
			||||||
 | 
					        speed = Math.abs(speed);
 | 
				
			||||||
 | 
					        speed = speed / 100 * 50;
 | 
				
			||||||
 | 
					        speed += 50;
 | 
				
			||||||
 | 
					        let c = Math.PI * (90 * 2);
 | 
				
			||||||
 | 
					        let pct = ((100 - speed) / 100) * c;
 | 
				
			||||||
 | 
					        this.circleBar.setAttribute('stroke-dashoffset', `${pct}`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -55,8 +55,8 @@
 | 
				
			|||||||
  "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|%|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|%",
 | 
				
			||||||
  "motors.SynchedMotorPair.tankFor|block": "tank %motors|%speedLeft|%|%speedRight|%|for %value|%unit",
 | 
					  "motors.SynchedMotorPair.tankFor|block": "tank %motors|%speedLeft|%|%speedRight|%|for %value|%unit",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,14 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					namespace motors {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * A speed picker
 | 
				
			||||||
 | 
					     * @param speed the speed
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    //% blockId=motorSpeedPicker block="%speed" shim=TD_ID
 | 
				
			||||||
 | 
					    //% speed.fieldEditor="speed" colorSecondary="#FFFFFF"
 | 
				
			||||||
 | 
					    //% weight=0 blockHidden=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();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user