microsoft / pxt-ev3

Microsoft MakeCode editor for the LEGO MINDSTORMS EV3 Brick
https://makecode.mindstorms.com/
Other
55 stars 39 forks source link

Can't put an angle with decimal point into a protractor #993

Open jfo8000 opened 3 years ago

jfo8000 commented 3 years ago

Looks like might be related to this change https://github.com/microsoft/pxt/pull/6026

https://makecode.com/playground#field-editors-protractor

Load up the protractor example Add a turn block Try to type 22.5 Result: floors to 22

With nashing of teeth I managed to fix it in my version... though I am having trouble with the editor coming through as a square block instead of a round one.

To work around the precision problem I called:
this.setConstraints('0', '360', undefined)

Here's my 360deg protractor. It's close to working

/// <reference path="../node_modules/pxt-core/localtypings/blockly.d.ts" />
/// <reference path="../node_modules/pxt-core/built/pxtsim.d.ts"/>
namespace pxt.editor {
    export interface FieldProtractorOptions360 extends Blockly.FieldCustomOptions {
        min? : number,
        max? : number,
        precision?: number,
        step? : number,
    }
    export class FieldProtractor360 extends Blockly.FieldSlider implements Blockly.FieldCustom {
        public isFieldCustom_ = true;
        private params: any;
        private circleSVG: SVGElement;
        private pieCircle: SVGCircleElement;
        private reporter: SVGTextElement;
        constructor(value_: any, params: FieldProtractorOptions360, opt_validator?: Function) {
            super(parseFloat(value_),
                 /*min*/ params.min === undefined ? '0' : params.min,  
                 /*max*/ params.max === undefined ? '360' : params.max , 
                 /*precision*/ params.precision === undefined ? undefined : params.precision, 
                 /*step*/ params.step === undefined ? '15' : params.step, 
                 /*labelText*/ lf("Angle"), 
                 /*validator*/ opt_validator);
            this.params = params;
        }
        createLabelDom_(labelText: string) {
            console.log("Field Editor", this)
            const labelContainer = document.createElement('div');
            this.circleSVG = document.createElementNS("http://www.w3.org/2000/svg", "svg") as SVGGElement;
            pxsim.svg.hydrate(this.circleSVG, {
                viewBox: "0 0 200 200",
                width: "170"
            });
            labelContainer.appendChild(this.circleSVG);
            const radius = 90;
            const circumference = 3.14 * radius*2;
            const centerViewBox = {x: 100, y: 100}
            const outerCircle = pxsim.svg.child(this.circleSVG, "circle", {
                'stroke-dasharray': circumference, 
                'stroke-dashoffset': '0',
                'cx': centerViewBox.x, 
                'cy': centerViewBox.y, 
                'r': radius, 
                'style': `fill:white;`,
                'stroke': '#a8aaa8', 'stroke-width': '1rem'
            }) as SVGCircleElement;
            this.pieCircle = pxsim.svg.child(this.circleSVG, "circle", 
            {
                'stroke-dasharray': circumference, 
                'stroke-dashoffset': '0',
                'cx': centerViewBox.x, 
                'cy': centerViewBox.y, 
                'r':  radius, 
                'style': `fill:transparent; transition: stroke-dashoffset 0.1s linear;`,
                'stroke': '#f12a21', 
                'transform': `rotate(-90)`,
                'transform-origin': 'center',
                'class': 'pieCircle',
                'stroke-width': '1em'
            }) as SVGCircleElement;
            this.reporter = pxsim.svg.child(this.circleSVG, "text", {
                'x':  centerViewBox.x+10, 'y':  centerViewBox.y,
                'text-anchor': 'middle', 
                'dominant-baseline': 'middle',
                'style': 'font-size: 36px;',
                'class': 'sim-text inverted number'
            }) as SVGTextElement;
            // labelContainer.setAttribute('class', 'blocklyFieldSliderLabel');
            const readout = document.createElement('span');
            readout.setAttribute('class', 'blocklyFieldSliderReadout');
            this.setConstraints('0', '360', undefined)
            return [labelContainer, readout];
        };
        setReadout_(readout: Element, value: string) {
            const angleValue = parseFloat(value)
            this.updateAngle(angleValue);
            const readoutText =  (value && value.toString().indexOf(".") >= 0) ? angleValue.toFixed(2) : value
            // Update reporter
            this.reporter.textContent = `${readoutText}°`;
        }
        private updateAngle(angle: number) {
            //angle = Math.max(0, Math.min(360, angle));
            const radius = 90;
            // set the dash offset to be the circumference
            // times the fraction of the angle. 
            const circumference =   3.14*(radius*2) 
            // for 360, 720, etc, show as a complete circle
            const angleFraction =(360-(angle%360))/360
            const isMultipleOf360BiggerThanZero = (angle > 0 && angleFraction === 1);
            const dashOffsetLength = (isMultipleOf360BiggerThanZero) ? 0: circumference* angleFraction
            this.pieCircle.setAttribute('stroke-dashoffset', `${Math.abs(dashOffsetLength)}`);
            if (dashOffsetLength < 0) {
                this.pieCircle.setAttribute('transform', 'rotate(-90) scale(-1, 1)');
            }
            else {
                this.pieCircle.setAttribute('transform', 'rotate(-90)');
            } 
        }
    }
}
jfo8000 commented 3 years ago

The "close to working" is I am stuck in an odd square text editor which I cannot drag into. Also the placement of the dropdown is in the wrong spot. Any thoughts there appreciated.

image image image

jfo8000 commented 3 years ago

Just wanted to post an update. I was able to successfully load the editor - looks like however I did my block editor definition was incorrect. So I now have this version successfully loaded up in BuildBee as an extension.

The original bug about decimal points in the protractor editor still stands.