2018-01-10 07:05:26 +01:00
|
|
|
/// <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,
|
2018-01-31 05:40:41 +01:00
|
|
|
'text-anchor': 'middle', 'dominant-baseline': 'middle',
|
2018-01-10 07:05:26 +01:00
|
|
|
'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_();
|
|
|
|
}
|
|
|
|
}
|