From 180f32f25c613495769029c7ff8d6282d7377c8e Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Fri, 22 Dec 2017 14:00:23 -0800 Subject: [PATCH 01/21] Simulator refactoring to support better resizing of modules and controls --- sim/dalboard.ts | 30 +- sim/state/color.ts | 8 +- sim/state/motors.ts | 1 + sim/state/uart.ts | 2 +- sim/visuals/board.ts | 154 ++++----- sim/visuals/controlView.ts | 32 +- sim/visuals/controls/closeIcon.ts | 11 + sim/visuals/controls/colorGrid.ts | 2 +- sim/visuals/controls/colorWheel.ts | 2 +- sim/visuals/controls/distanceSlider.ts | 3 +- sim/visuals/controls/rotationSlider.ts | 3 +- sim/visuals/layoutView.ts | 300 +++++++++++------- sim/visuals/nodes/brickView.ts | 10 +- sim/visuals/nodes/colorSensorView.ts | 6 +- sim/visuals/nodes/gyroSensorView.ts | 4 +- sim/visuals/nodes/largeMotorView.ts | 4 +- sim/visuals/nodes/mediumMotorView.ts | 6 +- .../nodes/{staticView.ts => moduleView.ts} | 17 +- sim/visuals/nodes/portView.ts | 4 +- sim/visuals/nodes/touchSensorView.ts | 4 +- sim/visuals/nodes/ultrasonicView.ts | 4 +- sim/visuals/view.ts | 89 +++++- sim/visuals/wireView.ts | 13 +- 23 files changed, 408 insertions(+), 301 deletions(-) rename sim/visuals/nodes/{staticView.ts => moduleView.ts} (87%) diff --git a/sim/dalboard.ts b/sim/dalboard.ts index 9ad960b8..b542acb0 100644 --- a/sim/dalboard.ts +++ b/sim/dalboard.ts @@ -23,20 +23,6 @@ namespace pxsim { } export class EV3Board extends CoreBoard { - // state & update logic for component services - // neopixelState: CommonNeoPixelState; - buttonState: EV3ButtonState; - slideSwitchState: SlideSwitchState; - lightSensorState: AnalogSensorState; - thermometerState: AnalogSensorState; - thermometerUnitState: number; - microphoneState: AnalogSensorState; - edgeConnectorState: EdgeConnectorState; - capacitiveSensorState: CapacitiveSensorState; - accelerometerState: AccelerometerState; - touchButtonState: TouchButtonState; - irState: InfraredState; - view: SVGSVGElement; outputState: EV3OutputState; @@ -86,11 +72,6 @@ namespace pxsim { // TODO break; } - case "irpacket": { - let ev = msg; - this.irState.receive(new RefBuffer(ev.packet)); - break; - } } } @@ -120,6 +101,9 @@ namespace pxsim { document.body.innerHTML = ""; // clear children document.body.appendChild(this.view = viewHost.getView() as SVGSVGElement); + this.inputNodes = []; + this.outputNodes = []; + return Promise.resolve(); } @@ -127,14 +111,6 @@ namespace pxsim { return svg.toDataUri(new XMLSerializer().serializeToString(this.view)); } - //defaultNeopixelPin() { - // return this.edgeConnectorState.getPin(CPlayPinName.D8); - //} - - getDefaultPitchPin() { - return this.edgeConnectorState.getPin(CPlayPinName.D6); - } - getBrickNode() { return this.brickNode; } diff --git a/sim/state/color.ts b/sim/state/color.ts index 42ce61df..ad5f7ac5 100644 --- a/sim/state/color.ts +++ b/sim/state/color.ts @@ -20,7 +20,7 @@ namespace pxsim { export class ColorSensorNode extends UartSensorNode { id = NodeType.ColorSensor; - private color: number; + private color: number = 50; constructor(port: number) { super(port); @@ -31,10 +31,8 @@ namespace pxsim { } setColor(color: number) { - if (this.color != color) { - this.color = color; - this.setChangedState(); - } + this.color = color; + this.setChangedState(); } getValue() { diff --git a/sim/state/motors.ts b/sim/state/motors.ts index fcf71bcd..8abb3c75 100644 --- a/sim/state/motors.ts +++ b/sim/state/motors.ts @@ -48,6 +48,7 @@ namespace pxsim { stop() { // TODO: implement + this.setSpeed(0); } start() { diff --git a/sim/state/uart.ts b/sim/state/uart.ts index eeabdb9d..cc612b03 100644 --- a/sim/state/uart.ts +++ b/sim/state/uart.ts @@ -88,7 +88,7 @@ namespace pxsim { const inputNodes = ev3board().getInputNodes(); for (let port = 0; port < DAL.NUM_INPUTS; port++) { const node = inputNodes[port]; - if (node) { + if (node && node.isUart()) { // Actual const index = 0; //UartOff.Actual + port * 2; util.map16Bit(data, UartOff.Raw + DAL.MAX_DEVICE_DATALENGTH * 300 * port + DAL.MAX_DEVICE_DATALENGTH * index, Math.floor(node.getValue())) diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index e6239b92..ba68a607 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -99,16 +99,9 @@ namespace pxsim.visuals { private layoutView: LayoutView; - private controlGroup: ViewContainer; - private selectedNode: NodeType; - private selectedPort: number; - private controlView: View; private cachedControlNodes: { [index: string]: View[] } = {}; private cachedDisplayViews: { [index: string]: LayoutElement[] } = {}; - private closeGroup: ViewContainer; - private closeIconView: View; - private screenCanvas: HTMLCanvasElement; private screenCanvasCtx: CanvasRenderingContext2D; private screenCanvasData: ImageData; @@ -143,7 +136,12 @@ namespace pxsim.visuals { Runtime.messagePosted = (msg) => { switch (msg.type || "") { - case "status": if ((msg as pxsim.SimulatorStateMessage).state == "killed") this.kill(); break; + case "status": { + const state = (msg as pxsim.SimulatorStateMessage).state; + if (state == "killed") this.kill(); + if (state == "running") this.begin(); + break; + } } } } @@ -177,36 +175,6 @@ namespace pxsim.visuals { this.layoutView.updateTheme(theme); } - public resize() { - const bounds = this.element.getBoundingClientRect(); - this.width = bounds.width; - this.height = bounds.height; - this.layoutView.layout(bounds.width, bounds.height); - - if (this.selectedNode) { - const scale = this.width / this.closeIconView.getInnerWidth() / 10; - // Translate close icon - this.closeIconView.scale(Math.max(0, Math.min(1, scale))); - const closeIconWidth = this.closeIconView.getWidth(); - const closeIconHeight = this.closeIconView.getHeight(); - const closeCoords = this.layoutView.getCloseIconCoords(closeIconWidth, closeIconHeight); - this.closeIconView.translate(closeCoords.x, closeCoords.y); - } - - if (this.controlView) { - const h = this.controlView.getInnerHeight(); - const w = this.controlView.getInnerWidth(); - const bh = this.layoutView.getModuleBounds().height - this.closeIconView.getHeight(); - const bw = this.layoutView.getModuleBounds().width - (this.width * MODULE_INNER_PADDING_RATIO * 2); - this.controlView.scale(Math.min(bh / h, bw / w), false); - - const controlCoords = this.layoutView.getSelectedCoords(); - this.controlView.translate(controlCoords.x, controlCoords.y); - } - - //this.updateScreen(); - } - private getControlForNode(id: NodeType, port: number) { if (this.cachedControlNodes[id] && this.cachedControlNodes[id][port]) { return this.cachedControlNodes[id][port]; @@ -285,6 +253,10 @@ namespace pxsim.visuals { return undefined; } + private getCloseIconView() { + return new CloseIconControl(this.element, this.defs, new PortNode(-1), -1); + } + private buildDom() { this.wrapper = document.createElement('div'); this.wrapper.style.display = 'inline'; @@ -299,25 +271,10 @@ namespace pxsim.visuals { this.layoutView = new LayoutView(); this.layoutView.inject(this.element); - this.controlGroup = new ViewContainer(); - this.controlGroup.inject(this.element); - - this.closeGroup = new ViewContainer(); - this.closeGroup.inject(this.element); - // Add EV3 module element this.layoutView.setBrick(new BrickView(-1)); - this.closeIconView = new CloseIconControl(this.element, this.defs, new PortNode(-1), -1); - this.closeIconView.registerClick(() => { - this.layoutView.clearSelected(); - this.updateState(); - }) - this.closeGroup.addView(this.closeIconView); - this.closeIconView.setVisible(false); - this.resize(); - //this.updateState(); // Add Screen canvas to board this.buildScreenCanvas(); @@ -329,6 +286,22 @@ namespace pxsim.visuals { window.addEventListener("resize", e => { this.resize(); }); + + setTimeout(() => { + this.resize(); + }, 200); + } + + public resize() { + if (!this.element) return; + const bounds = this.element.getBoundingClientRect(); + this.width = bounds.width; + this.height = bounds.height; + this.layoutView.layout(bounds.width, bounds.height); + + this.updateState(); + let state = ev3board().screenState; + this.updateScreenStep(state); } private buildScreenCanvas() { @@ -357,12 +330,27 @@ namespace pxsim.visuals { } private kill() { - if (this.lastAnimationId) cancelAnimationFrame(this.lastAnimationId); + this.running = false; + if (this.lastAnimationIds.length > 0) { + this.lastAnimationIds.forEach(animationId => { + cancelAnimationFrame(animationId); + }) + } } - private lastAnimationId: number; + private begin() { + this.running = true; + } + + private running: boolean = false; + private lastAnimationIds: number[] = []; public updateState() { - if (this.lastAnimationId) cancelAnimationFrame(this.lastAnimationId); + if (this.lastAnimationIds.length > 0) { + this.lastAnimationIds.forEach(animationId => { + cancelAnimationFrame(animationId); + }) + } + if (!this.running) return; const fps = GAME_LOOP_FPS; let now; let then = Date.now(); @@ -370,7 +358,8 @@ namespace pxsim.visuals { let delta; let that = this; function loop() { - that.lastAnimationId = requestAnimationFrame(loop); + const animationId = requestAnimationFrame(loop); + that.lastAnimationIds.push(animationId); now = Date.now(); delta = now - then; if (delta > interval) { @@ -382,67 +371,46 @@ namespace pxsim.visuals { } private updateStateStep(elapsed: number) { - const selected = this.layoutView.getSelected(); - let selectedChanged = false; const inputNodes = ev3board().getInputNodes(); inputNodes.forEach((node, index) => { node.updateState(elapsed); - if (!node.didChange()) return; const view = this.getDisplayViewForNode(node.id, index); + if (!node.didChange() && !view.didChange()) return; if (view) { - this.layoutView.setInput(index, view); + const control = view.getSelected() ? this.getControlForNode(node.id, index) : undefined; + const closeIcon = control ? this.getCloseIconView() : undefined; + this.layoutView.setInput(index, view, control, closeIcon); view.updateState(); - if (selected == view) selectedChanged = true; + if (control) control.updateState(); } }); const brickNode = ev3board().getBrickNode(); if (brickNode.didChange()) { - this.getDisplayViewForNode(ev3board().getBrickNode().id, -1).updateState(); + this.getDisplayViewForNode(brickNode.id, -1).updateState(); } const outputNodes = ev3board().getMotors(); outputNodes.forEach((node, index) => { node.updateState(elapsed); - if (!node.didChange()) return; const view = this.getDisplayViewForNode(node.id, index); + if (!node.didChange() && !view.didChange()) return; if (view) { - this.layoutView.setOutput(index, view); + const control = view.getSelected() ? this.getControlForNode(node.id, index) : undefined; + const closeIcon = control ? this.getCloseIconView() : undefined; + this.layoutView.setOutput(index, view, control, closeIcon); view.updateState(); - if (selected == view) selectedChanged = true; + if (control) control.updateState(); } }); - if (selected && (selected.getId() !== this.selectedNode || selected.getPort() !== this.selectedPort)) { - this.selectedNode = selected.getId(); - this.selectedPort = selected.getPort(); - this.controlGroup.clear(); - const control = this.getControlForNode(this.selectedNode, selected.getPort()); - if (control) { - this.controlView = control; - this.controlGroup.addView(control); - } - this.closeIconView.setVisible(true); - this.resize(); - } else if (!selected) { - this.controlGroup.clear(); - this.controlView = undefined; - this.selectedNode = undefined; - this.selectedPort = undefined; - this.closeIconView.setVisible(false); + let state = ev3board().screenState; + if (!state.didChange()) { + this.updateScreenStep(state); } - - if (selectedChanged && selected) { - this.controlView.updateState(); - } - - this.updateScreenStep(); } - private updateScreenStep() { - let state = ev3board().screenState; - if (!state.didChange()) return; - + private updateScreenStep(state: EV3ScreenState) { const bBox = this.layoutView.getBrick().getScreenBBox(); if (!bBox || bBox.width == 0) return; diff --git a/sim/visuals/controlView.ts b/sim/visuals/controlView.ts index 6d0fa6a9..6c9f1dd5 100644 --- a/sim/visuals/controlView.ts +++ b/sim/visuals/controlView.ts @@ -1,4 +1,4 @@ -/// +/// namespace pxsim.visuals { @@ -6,7 +6,7 @@ namespace pxsim.visuals { export const CONTROL_HEIGHT = 175; export abstract class ControlView extends SimView implements LayoutElement { - private background: SVGSVGElement; + protected content: SVGSVGElement; abstract getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement): SVGElement; @@ -34,18 +34,30 @@ namespace pxsim.visuals { return false; } - buildDom(width: number): SVGElement { - this.background = svg.elt("svg", { height: "100%", width: "100%"}) as SVGSVGElement; - this.background.appendChild(this.getInnerView(this.parent, this.globalDefs)); - return this.background; + buildDom(): SVGElement { + this.content = svg.elt("svg", { viewBox: `0 0 ${this.getInnerWidth()} ${this.getInnerHeight()}`}) as SVGSVGElement; + this.content.appendChild(this.getInnerView(this.parent, this.globalDefs)); + return this.content; + } + + public resize(width: number, height: number) { + super.resize(width, height); + this.updateDimensions(width, height); + } + + private updateDimensions(width: number, height: number) { + if (this.content) { + const currentWidth = this.getInnerWidth(); + const currentHeight = this.getInnerHeight(); + const newHeight = currentHeight / currentWidth * width; + const newWidth = currentWidth / currentHeight * height; + this.content.setAttribute('width', `${width}`); + this.content.setAttribute('height', `${newHeight}`); + } } onComponentVisible() { } - - getWeight() { - return 0; - } } } \ No newline at end of file diff --git a/sim/visuals/controls/closeIcon.ts b/sim/visuals/controls/closeIcon.ts index 02b5307f..f16b1650 100644 --- a/sim/visuals/controls/closeIcon.ts +++ b/sim/visuals/controls/closeIcon.ts @@ -17,6 +17,17 @@ namespace pxsim.visuals { return this.closeGroup; } + + buildDom(): SVGElement { + this.content = svg.elt("svg", { width: "100%", height: "100%"}) as SVGSVGElement; + this.content.appendChild(this.getInnerView()); + return this.content; + } + + public resize(width: number, height: number) { + super.resize(width, height); + } + public getInnerHeight() { return 32; } diff --git a/sim/visuals/controls/colorGrid.ts b/sim/visuals/controls/colorGrid.ts index f8faca73..c1d6b6fc 100644 --- a/sim/visuals/controls/colorGrid.ts +++ b/sim/visuals/controls/colorGrid.ts @@ -7,7 +7,7 @@ namespace pxsim.visuals { getInnerView() { this.group = svg.elt("g") as SVGGElement; - this.group.setAttribute("transform", `translate(17, ${35 + this.getHeight() / 4}) scale(5)`) + this.group.setAttribute("transform", `translate(17, ${20 + this.getHeight() / 4}) scale(5)`) const colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey']; const colors = ['#f12a21', '#ffd01b', '#006db3', '#00934b', '#000', '#6c2d00']; diff --git a/sim/visuals/controls/colorWheel.ts b/sim/visuals/controls/colorWheel.ts index 80ff4ccf..0d20763f 100644 --- a/sim/visuals/controls/colorWheel.ts +++ b/sim/visuals/controls/colorWheel.ts @@ -10,7 +10,7 @@ namespace pxsim.visuals { getInnerView(parent: SVGSVGElement) { this.defs = svg.child(this.element, "defs", {}); this.group = svg.elt("g") as SVGGElement; - this.group.setAttribute("transform", `translate(12, ${this.getHeight() / 2 - 15}) scale(2.5)`) + this.group.setAttribute("transform", `translate(12, ${this.getHeight() / 2 - 15}) scale(2)`) let gc = "gradient-color"; this.colorGradient = svg.linearGradient(this.defs, gc, true); diff --git a/sim/visuals/controls/distanceSlider.ts b/sim/visuals/controls/distanceSlider.ts index 033b8b0d..d3b28cce 100644 --- a/sim/visuals/controls/distanceSlider.ts +++ b/sim/visuals/controls/distanceSlider.ts @@ -100,7 +100,8 @@ namespace pxsim.visuals { private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) { let cur = svg.cursorPoint(pt, parent, ev); const height = this.getContentHeight(); //DistanceSliderControl.SLIDER_HEIGHT; - let t = Math.max(0, Math.min(1, (this.getTopPadding() + height + this.top / this.scaleFactor - cur.y / this.scaleFactor) / height)) + const bBox = this.content.getBoundingClientRect(); + let t = Math.max(0, Math.min(1, (this.getTopPadding() + height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height)) const state = this.state; state.setDistance((1 - t) * (this.getMax())); diff --git a/sim/visuals/controls/rotationSlider.ts b/sim/visuals/controls/rotationSlider.ts index df5d8117..3858c53a 100644 --- a/sim/visuals/controls/rotationSlider.ts +++ b/sim/visuals/controls/rotationSlider.ts @@ -83,7 +83,8 @@ namespace pxsim.visuals { private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) { let cur = svg.cursorPoint(pt, parent, ev); const width = CONTROL_WIDTH; //DistanceSliderControl.SLIDER_HEIGHT; - let t = Math.max(0, Math.min(1, (width + this.left / this.scaleFactor - cur.x / this.scaleFactor) / width)) + const bBox = this.content.getBoundingClientRect(); + let t = Math.max(0, Math.min(1, (width + bBox.left / this.scaleFactor - cur.x / this.scaleFactor) / width)) const state = this.state; state.setAngle((1 - t) * (100)); diff --git a/sim/visuals/layoutView.ts b/sim/visuals/layoutView.ts index a72cc5f0..5a70217e 100644 --- a/sim/visuals/layoutView.ts +++ b/sim/visuals/layoutView.ts @@ -1,5 +1,5 @@ /// -/// +/// /// namespace pxsim.visuals { @@ -9,59 +9,51 @@ namespace pxsim.visuals { export const BRICK_HEIGHT_RATIO = 1 / 3; export const MODULE_AND_WIRING_HEIGHT_RATIO = 1 / 3; // For inputs and outputs - export const MODULE_HEIGHT_RATIO = MODULE_AND_WIRING_HEIGHT_RATIO * 3 / 4; - export const WIRING_HEIGHT_RATIO = MODULE_AND_WIRING_HEIGHT_RATIO / 4; + export const MODULE_HEIGHT_RATIO = MODULE_AND_WIRING_HEIGHT_RATIO * 4 / 5; + export const WIRING_HEIGHT_RATIO = MODULE_AND_WIRING_HEIGHT_RATIO / 5; export const MODULE_INNER_PADDING_RATIO = 1 / 35; + export const MAX_MODULE_WIDTH = 100; + export interface LayoutElement extends View { getId(): number; getPort(): number; getPaddingRatio(): number; getWiringRatio(): number; - setSelected(selected: boolean): void; } export class LayoutView extends ViewContainer { private inputs: LayoutElement[] = []; private outputs: LayoutElement[] = []; + private inputContainers: ViewContainer[] = []; + private outputContainers: ViewContainer[] = []; + + private inputControls: View[] = []; + private outputControls: View[] = []; + + private inputCloseIcons: View[] = []; + private outputCloseIcons: View[] = []; + private inputWires: WireView[] = []; private outputWires: WireView[] = []; - private selected: number; - private selectedIsInput: boolean; private brick: BrickView; private offsets: number[]; private contentGroup: SVGGElement; private scrollGroup: SVGGElement; private renderedViews: Map = {}; - - private childScaleFactor: number; - - private totalLength: number; - private height: number; private hasDimensions = false; constructor() { super(); - this.outputs = [ - new PortView(0, 'A'), - new PortView(1, 'B'), - new PortView(2, 'C'), - new PortView(3, 'D') - ]; + this.outputContainers = [new ViewContainer(), new ViewContainer, new ViewContainer(), new ViewContainer()]; + this.inputContainers = [new ViewContainer(), new ViewContainer, new ViewContainer(), new ViewContainer()]; this.brick = new BrickView(0); - this.inputs = [ - new PortView(0, '1'), - new PortView(1, '2'), - new PortView(2, '3'), - new PortView(3, '4') - ]; - for (let port = 0; port < DAL.NUM_OUTPUTS; port++) { this.outputWires[port] = new WireView(port); } @@ -72,8 +64,7 @@ namespace pxsim.visuals { public layout(width: number, height: number) { this.hasDimensions = true; - this.width = width; - this.height = height; + this.resize(width, height); this.scrollGroup.setAttribute("width", width.toString()); this.scrollGroup.setAttribute("height", height.toString()); this.position(); @@ -81,6 +72,7 @@ namespace pxsim.visuals { public setBrick(brick: BrickView) { this.brick = brick; + this.brick.inject(this.scrollGroup); this.position(); } @@ -88,55 +80,112 @@ namespace pxsim.visuals { return this.brick; } - public setInput(port: number, child: LayoutElement) { - if (this.inputs[port]) { - // Remove current input - this.inputs[port].dispose(); + public setInput(port: number, view: LayoutElement, control?: View, closeIcon?: View) { + if (this.inputs[port] != view || this.inputControls[port] != control) { + if (this.inputs[port]) { + // Remove current input + this.inputs[port].dispose(); + } + this.inputs[port] = view; + if (this.inputControls[port]) { + this.inputControls[port].dispose(); + } + this.inputControls[port] = control; + this.inputCloseIcons[port] = closeIcon; + + this.inputContainers[port].clear(); + this.inputContainers[port].addView(view); + + if (control) this.inputContainers[port].addView(control); + + if (view.hasClick()) view.registerClick((ev: any) => { + view.setSelected(true); + runtime.queueDisplayUpdate(); + }, true); + + if (control && closeIcon) { + this.inputContainers[port].addView(closeIcon); + closeIcon.registerClick(() => { + // Clear selection + view.setSelected(false); + runtime.queueDisplayUpdate(); + }) + } } - this.inputs[port] = child; + this.position(); } - public setOutput(port: number, child: LayoutElement) { - if (this.outputs[port]) { - // Remove current input - this.outputs[port].dispose(); + public setOutput(port: number, view: LayoutElement, control?: View, closeIcon?: View) { + if (this.outputs[port] != view || this.outputControls[port] != control) { + if (this.outputs[port]) { + // Remove current output + this.outputs[port].dispose(); + } + this.outputs[port] = view; + if (this.outputControls[port]) { + this.outputControls[port].dispose(); + } + this.outputControls[port] = control; + this.outputCloseIcons[port] = closeIcon; + + this.outputContainers[port].clear(); + this.outputContainers[port].addView(view); + + if (control) this.outputContainers[port].addView(control); + + if (view.hasClick()) view.registerClick((ev: any) => { + view.setSelected(true); + runtime.queueDisplayUpdate(); + }, true) + + if (control && closeIcon) { + this.outputContainers[port].addView(closeIcon); + closeIcon.registerClick(() => { + // Clear selection + view.setSelected(false); + runtime.queueDisplayUpdate(); + }) + } } - this.outputs[port] = child; + this.position(); } - public onClick(index: number, input: boolean, ev: any) { - this.setSelected(index, input); - } - - public clearSelected() { - this.selected = undefined; - this.selectedIsInput = undefined; - } - - public setSelected(index: number, input?: boolean) { - if (index !== this.selected || input !== this.selectedIsInput) { - this.selected = index; - this.selectedIsInput = input; - const node = this.getSelected(); - if (node) node.setSelected(true); - - //this.redoPositioning(); - runtime.queueDisplayUpdate(); - } - } - - public getSelected() { - if (this.selected !== undefined) { - return this.selectedIsInput ? this.inputs[this.selected] : this.outputs[this.selected]; - } - return undefined; - } - - protected buildDom(width: number) { + protected buildDom() { this.contentGroup = svg.elt("g") as SVGGElement; this.scrollGroup = svg.child(this.contentGroup, "g") as SVGGElement; + + // Inject all view containers + for (let i = 0; i < 4; i++) { + this.inputContainers[i].inject(this.scrollGroup); + this.outputContainers[i].inject(this.scrollGroup); + } + + this.inputs = []; + this.outputs = []; + this.inputControls = []; + this.outputControls = []; + + // Inject all wires + for (let port = 0; port < DAL.NUM_OUTPUTS; port++) { + this.outputWires[port].inject(this.scrollGroup); + } + for (let port = 0; port < DAL.NUM_INPUTS; port++) { + this.inputWires[port].inject(this.scrollGroup); + } + + // Inject all ports + this.setInput(0, new PortView(0, 'A')); + this.setInput(1, new PortView(1, 'B')); + this.setInput(2, new PortView(2, 'C')); + this.setInput(3, new PortView(3, 'D')); + + this.setOutput(0, new PortView(0, '1')); + this.setOutput(1, new PortView(1, '2')); + this.setOutput(2, new PortView(2, '3')); + this.setOutput(3, new PortView(3, '4')); + return this.contentGroup; } @@ -171,34 +220,47 @@ namespace pxsim.visuals { this.offsets = []; - const selectedNode = this.getSelected(); - const contentWidth = this.width || DEFAULT_WIDTH; const contentHeight = this.height || DEFAULT_HEIGHT; const moduleHeight = this.getModuleHeight(); const brickHeight = this.getBrickHeight(); - this.brick.inject(this.scrollGroup); const brickWidth = this.brick.getInnerWidth() / this.brick.getInnerHeight() * brickHeight; const brickPadding = (contentWidth - brickWidth) / 2; - const modulePadding = contentWidth / 35; + const modulePadding = this.getModulePadding(); const moduleSpacing = contentWidth / 4; - const moduleWidth = moduleSpacing - (modulePadding * 2); - let currentX = modulePadding; + const moduleWidth = this.getInnerModuleWidth(); + let currentX = this.getModulePadding(); let currentY = 0; this.outputs.forEach((n, i) => { - const outputPadding = moduleWidth * n.getPaddingRatio(); - const outputWidth = moduleWidth - outputPadding * 2; - n.inject(this.scrollGroup, outputWidth); - n.resize(outputWidth); - const nHeight = n.getHeight() / n.getWidth() * outputWidth; - n.translate(currentX + outputPadding, currentY + moduleHeight - nHeight); - n.setSelected(n == selectedNode); - if (n.hasClick()) n.registerClick((ev: any) => { - this.onClick(i, false, ev); - }) + this.outputContainers[i].translate(currentX, currentY); + if (this.outputs[i]) { + const view = this.outputs[i]; + const outputPadding = this.getInnerModuleWidth() * view.getPaddingRatio(); + const desiredOutputWidth = this.getInnerModuleWidth() - outputPadding * 2; + const outputWidth = Math.min(desiredOutputWidth, MAX_MODULE_WIDTH); + const outputHeight = this.getModuleHeight(); + + // Translate and resize view + view.resize(outputWidth, outputHeight); + const viewHeight = view.getInnerHeight() / view.getInnerWidth() * outputWidth; + view.translate(outputPadding + ((desiredOutputWidth - outputWidth) / 2), outputHeight - viewHeight, true); + + // Resize control + const control = this.outputControls[i]; + if (control) { + control.resize(this.getInnerModuleWidth(), outputHeight); + + // Translate close icon + const closeIcon = this.outputCloseIcons[i]; + if (closeIcon) { + const closeIconWidth = closeIcon.getWidth(); + closeIcon.translate(this.getInnerModuleWidth() / 2 - closeIconWidth / 2, 0); + } + } + } currentX += moduleSpacing; }) @@ -206,7 +268,7 @@ namespace pxsim.visuals { currentY = moduleHeight; const wireBrickSpacing = brickWidth / 5; - const wiringYPadding = 10; + const wiringYPadding = 0; let wireStartX = 0; let wireEndX = brickPadding + wireBrickSpacing; let wireEndY = currentY + this.getWiringHeight() + wiringYPadding; @@ -214,7 +276,6 @@ namespace pxsim.visuals { // Draw output lines for (let port = 0; port < DAL.NUM_OUTPUTS; port++) { - if (!this.outputWires[port].isRendered()) this.outputWires[port].inject(this.scrollGroup); this.outputWires[port].updateDimensions(wireStartX + moduleSpacing * this.outputs[port].getWiringRatio(), wireStartY, wireEndX, wireEndY); this.outputWires[port].setSelected(this.outputs[port].getId() == NodeType.Port); wireStartX += moduleSpacing; @@ -225,22 +286,39 @@ namespace pxsim.visuals { currentY += this.getWiringHeight(); // Render the brick in the middle - this.brick.resize(brickWidth); + this.brick.resize(brickWidth, brickHeight); this.brick.translate(currentX, currentY); currentX = modulePadding; currentY += brickHeight + this.getWiringHeight(); this.inputs.forEach((n, i) => { - const inputPadding = moduleWidth * n.getPaddingRatio(); - const inputWidth = moduleWidth - inputPadding * 2; - n.inject(this.scrollGroup, inputWidth); - n.resize(inputWidth); - n.translate(currentX + inputPadding, currentY); - n.setSelected(n == selectedNode); - if (n.hasClick()) n.registerClick((ev: any) => { - this.onClick(i, true, ev); - }) + this.inputContainers[i].translate(currentX, currentY); + if (this.inputs[i]) { + const view = this.inputs[i]; + const inputPadding = this.getInnerModuleWidth() * view.getPaddingRatio(); + const desiredInputWidth = this.getInnerModuleWidth() - inputPadding * 2; + const inputWidth = Math.min(desiredInputWidth, MAX_MODULE_WIDTH); + const inputHeight = this.getModuleHeight(); + + // Translate and resize view + view.resize(inputWidth, inputHeight); + view.translate(inputPadding + ((desiredInputWidth - inputWidth) / 2), 0, true); + + // Resize control + const control = this.inputControls[i]; + if (control) { + control.resize(this.getInnerModuleWidth(), inputHeight); + + // Translate and resize close icon + const closeIcon = this.inputCloseIcons[i]; + if (closeIcon) { + const closeIconWidth = closeIcon.getWidth(); + const closeIconHeight = closeIcon.getHeight(); + closeIcon.translate(this.getInnerModuleWidth() / 2 - closeIconWidth / 2, this.getModuleHeight() - closeIconHeight); + } + } + } currentX += moduleSpacing; }) @@ -251,7 +329,6 @@ namespace pxsim.visuals { // Draw input lines for (let port = 0; port < DAL.NUM_INPUTS; port++) { - if (!this.inputWires[port].isRendered()) this.inputWires[port].inject(this.scrollGroup); this.inputWires[port].updateDimensions(wireStartX, wireStartY, wireEndX, wireEndY); this.inputWires[port].setSelected(this.inputs[port].getId() == NodeType.Port); wireStartX += moduleSpacing; @@ -259,27 +336,6 @@ namespace pxsim.visuals { } } - public getSelectedCoords() { - const selected = this.getSelected(); - if (!selected) return undefined; - const port = this.getSelected().getPort(); - return { - x: this.getSelected().getPort() * this.width / 4 + this.width * MODULE_INNER_PADDING_RATIO, - y: this.selectedIsInput ? this.getModuleHeight() + 2 * this.getWiringHeight() + this.getBrickHeight() : this.getModuleHeight() / 4 - } - } - - public getCloseIconCoords(closeIconWidth: number, closeIconHeight: number) { - return { - x: this.getSelected().getPort() * this.width / 4 + this.getModuleBounds().width / 2 - closeIconWidth / 2, - y: this.selectedIsInput ? this.getModuleHeight() + 2 * this.getWiringHeight() + this.getBrickHeight() + this.getModuleHeight() - closeIconHeight : 0 - } - } - - public getModuleHeight() { - return (this.height || DEFAULT_HEIGHT) * MODULE_HEIGHT_RATIO; - } - public getBrickHeight() { return (this.height || DEFAULT_HEIGHT) * BRICK_HEIGHT_RATIO; } @@ -290,9 +346,21 @@ namespace pxsim.visuals { public getModuleBounds() { return { - width: this.width / 4, + width: (this.width || DEFAULT_WIDTH) / 4, height: this.getModuleHeight() } } + + public getModulePadding() { + return this.getModuleBounds().width / 35; + } + + public getInnerModuleWidth() { + return this.getModuleBounds().width - (this.getModulePadding() * 2); + } + + public getModuleHeight() { + return (this.height || DEFAULT_HEIGHT) * MODULE_HEIGHT_RATIO; + } } } \ No newline at end of file diff --git a/sim/visuals/nodes/brickView.ts b/sim/visuals/nodes/brickView.ts index 8619f053..6a732713 100644 --- a/sim/visuals/nodes/brickView.ts +++ b/sim/visuals/nodes/brickView.ts @@ -1,8 +1,8 @@ -/// +/// namespace pxsim.visuals { - export class BrickView extends StaticModuleView implements LayoutElement { + export class BrickView extends ModuleView implements LayoutElement { private static EV3_SCREEN_ID = "ev3_screen"; private static EV3_LIGHT_ID = "btn_color"; @@ -41,9 +41,9 @@ namespace pxsim.visuals { public updateThemeCore() { let theme = this.theme; - svg.fill(this.buttons[0], theme.buttonUps[0]); - svg.fill(this.buttons[1], theme.buttonUps[1]); - svg.fill(this.buttons[2], theme.buttonUps[2]); + // svg.fill(this.buttons[0], theme.buttonUps[0]); + // svg.fill(this.buttons[1], theme.buttonUps[1]); + // svg.fill(this.buttons[2], theme.buttonUps[2]); } private lastLightPattern: number = -1; diff --git a/sim/visuals/nodes/colorSensorView.ts b/sim/visuals/nodes/colorSensorView.ts index 19ee2ed7..6a1dc560 100644 --- a/sim/visuals/nodes/colorSensorView.ts +++ b/sim/visuals/nodes/colorSensorView.ts @@ -1,7 +1,7 @@ -/// +/// namespace pxsim.visuals { - export class ColorSensorView extends StaticModuleView implements LayoutElement { + export class ColorSensorView extends ModuleView implements LayoutElement { private control: ColorGridControl; @@ -10,7 +10,7 @@ namespace pxsim.visuals { } public getPaddingRatio() { - return 1 / 8; + return 1 / 6; } public updateState() { diff --git a/sim/visuals/nodes/gyroSensorView.ts b/sim/visuals/nodes/gyroSensorView.ts index c8280f8d..879e3d94 100644 --- a/sim/visuals/nodes/gyroSensorView.ts +++ b/sim/visuals/nodes/gyroSensorView.ts @@ -1,7 +1,7 @@ -/// +/// namespace pxsim.visuals { - export class GyroSensorView extends StaticModuleView implements LayoutElement { + export class GyroSensorView extends ModuleView implements LayoutElement { constructor(port: number) { super(GYRO_SVG, "gyro", NodeType.GyroSensor, port); diff --git a/sim/visuals/nodes/largeMotorView.ts b/sim/visuals/nodes/largeMotorView.ts index 42aeb2e8..6fb728fe 100644 --- a/sim/visuals/nodes/largeMotorView.ts +++ b/sim/visuals/nodes/largeMotorView.ts @@ -1,7 +1,7 @@ -/// +/// namespace pxsim.visuals { - export class LargeMotorView extends StaticModuleView implements LayoutElement { + export class LargeMotorView extends ModuleView implements LayoutElement { private static ROTATING_ECLIPSE_ID = "1eb2ae58-2419-47d4-86bf-4f26a7f0cf61"; diff --git a/sim/visuals/nodes/mediumMotorView.ts b/sim/visuals/nodes/mediumMotorView.ts index 546b7e4a..10371475 100644 --- a/sim/visuals/nodes/mediumMotorView.ts +++ b/sim/visuals/nodes/mediumMotorView.ts @@ -1,10 +1,10 @@ -/// +/// namespace pxsim.visuals { export const MOTOR_ROTATION_FPS = 32; - export class MediumMotorView extends StaticModuleView implements LayoutElement { + export class MediumMotorView extends ModuleView implements LayoutElement { private static ROTATING_ECLIPSE_ID = "Hole"; @@ -16,7 +16,7 @@ namespace pxsim.visuals { } public getPaddingRatio() { - return 1 / 10; + return 1 / 5; } updateState() { diff --git a/sim/visuals/nodes/staticView.ts b/sim/visuals/nodes/moduleView.ts similarity index 87% rename from sim/visuals/nodes/staticView.ts rename to sim/visuals/nodes/moduleView.ts index 1527c433..051f074d 100644 --- a/sim/visuals/nodes/staticView.ts +++ b/sim/visuals/nodes/moduleView.ts @@ -1,6 +1,6 @@ namespace pxsim.visuals { - export class StaticModuleView extends View implements LayoutElement { + export class ModuleView extends View implements LayoutElement { protected content: SVGSVGElement; protected controlShown: boolean; @@ -45,9 +45,8 @@ namespace pxsim.visuals { return 0.5; } - protected buildDom(width: number): SVGElement { + protected buildDom(): SVGElement { this.content = svg.parseString(this.xml); - this.updateDimensions(width); this.buildDomCore(); this.attachEvents(); if (this.hasClick()) @@ -82,15 +81,17 @@ namespace pxsim.visuals { public attachEvents() { } - public resize(width: number) { - this.updateDimensions(width); + public resize(width: number, height: number) { + super.resize(width, height); + this.updateDimensions(width, height); } - private updateDimensions(width: number) { + private updateDimensions(width: number, height: number) { if (this.content) { const currentWidth = this.getInnerWidth(); const currentHeight = this.getInnerHeight(); const newHeight = currentHeight / currentWidth * width; + const newWidth = currentWidth / currentHeight * height; this.content.setAttribute('width', `${width}`); this.content.setAttribute('height', `${newHeight}`); } @@ -101,13 +102,13 @@ namespace pxsim.visuals { } public setSelected(selected: boolean) { - this.selected = selected; + super.setSelected(selected); this.updateOpacity(); } protected updateOpacity() { if (this.rendered) { - const opacity = this.selected ? "0.5" : "1"; + const opacity = this.selected ? "0.2" : "1"; if (this.hasClick()) { this.setOpacity(opacity); if (this.selected) this.content.style.cursor = ""; diff --git a/sim/visuals/nodes/portView.ts b/sim/visuals/nodes/portView.ts index 5399713f..53908c75 100644 --- a/sim/visuals/nodes/portView.ts +++ b/sim/visuals/nodes/portView.ts @@ -1,8 +1,8 @@ -/// +/// namespace pxsim.visuals { - export class PortView extends StaticModuleView implements LayoutElement { + export class PortView extends ModuleView implements LayoutElement { constructor(port: NodeType, private label: string) { super(PORT_SVG, "port", NodeType.Port, port); diff --git a/sim/visuals/nodes/touchSensorView.ts b/sim/visuals/nodes/touchSensorView.ts index 0c623218..c86e88e9 100644 --- a/sim/visuals/nodes/touchSensorView.ts +++ b/sim/visuals/nodes/touchSensorView.ts @@ -1,7 +1,7 @@ -/// +/// namespace pxsim.visuals { - export class TouchSensorView extends StaticModuleView implements LayoutElement { + export class TouchSensorView extends ModuleView implements LayoutElement { private static RECT_ID = ["touch_gradient4", "touch_gradient3", "touch_gradient2", "touch_gradient1"]; private static TOUCH_GRADIENT_UNPRESSED = ["linear-gradient-2", "linear-gradient-3", "linear-gradient-4", "linear-gradient-5"]; diff --git a/sim/visuals/nodes/ultrasonicView.ts b/sim/visuals/nodes/ultrasonicView.ts index d370bd35..5ae9565b 100644 --- a/sim/visuals/nodes/ultrasonicView.ts +++ b/sim/visuals/nodes/ultrasonicView.ts @@ -1,7 +1,7 @@ -/// +/// namespace pxsim.visuals { - export class UltrasonicSensorView extends StaticModuleView implements LayoutElement { + export class UltrasonicSensorView extends ModuleView implements LayoutElement { constructor(port: number) { super(ULTRASONIC_SVG, "ultrasonic", NodeType.UltrasonicSensor, port); diff --git a/sim/visuals/view.ts b/sim/visuals/view.ts index 029f139d..7e46300c 100644 --- a/sim/visuals/view.ts +++ b/sim/visuals/view.ts @@ -3,14 +3,19 @@ namespace pxsim.visuals { protected element: SVGGElement; protected rendered = false; protected visible = false; + protected selected: boolean; protected width: number = 0; + protected height: number = 0; protected left: number = 0; protected top: number = 0; protected scaleFactor: number = 1; + private changed: boolean; + private hover: boolean = false; + protected theme: IBoardTheme; - protected abstract buildDom(width: number): SVGElement; + protected abstract buildDom(): SVGElement; public abstract getInnerWidth(): number; public abstract getInnerHeight(): number; @@ -83,9 +88,26 @@ namespace pxsim.visuals { } private onClickHandler: (ev: any) => void; - public registerClick(handler: (ev: any) => void) { + public registerClick(handler: (ev: any) => void, zoom?: boolean) { this.onClickHandler = handler; - this.getView().addEventListener(pointerEvents.up, this.onClickHandler); + if (zoom) { + this.getView().addEventListener(pointerEvents.up, (ev: any) => { + if (!this.getSelected()) { + this.onClickHandler(ev); + this.setHover(false); + } + }); + this.getView().addEventListener(pointerEvents.move, () => { + if (!this.getSelected()) { + this.setHover(true); + } + }); + this.getView().addEventListener(pointerEvents.leave, () => { + this.setHover(false); + }); + } else { + this.getView().addEventListener(pointerEvents.up, this.onClickHandler); + } } public dispose() { @@ -98,7 +120,7 @@ namespace pxsim.visuals { this.element = svg.elt("g") as SVGGElement; View.track(this); - const content = this.buildDom(this.width); + const content = this.buildDom(); if (content) { this.element.appendChild(content); } @@ -108,16 +130,30 @@ namespace pxsim.visuals { return this.element; } - public resize(width: number) { + public resize(width: number, height: number) { this.width = width; + this.height = height; } private updateTransform() { if (this.rendered) { - let transform = `translate(${this.left} ${this.top})`; + let left = this.left; + let top = this.top; + let scaleFactor = this.scaleFactor; + if (this.hover) { + const hoverScaleFactor = scaleFactor + 0.05; + // Scale around center of module + const centerX = this.getWidth() / 2; + const centerY = this.getHeight() / 2; + left = left - centerX * (hoverScaleFactor - 1); + top = top - centerY * (hoverScaleFactor - 1); + scaleFactor = hoverScaleFactor; + } - if (this.scaleFactor !== 1) { - transform += ` scale(${this.scaleFactor})`; + let transform = `translate(${left} ${top})`; + + if (scaleFactor !== 1) { + transform += ` scale(${scaleFactor})`; } this.element.setAttribute("transform", transform); @@ -149,6 +185,41 @@ namespace pxsim.visuals { delete View.allViews[id]; } } + + ///////// HOVERED STATE ///////////// + + public getHover() { + return this.hover; + } + + public setHover(hover: boolean) { + if (this.hover != hover) { + this.hover = hover; + this.updateTransform(); + } + } + + ///////// SELECTED STATE ///////////// + + public getSelected() { + return this.selected; + } + + public setSelected(selected: boolean) { + this.selected = selected; + this.setChangedState(); + } + + protected setChangedState() { + this.changed = true; + } + + public didChange() { + const res = this.changed; + this.changed = false; + return res; + } + } export abstract class SimView extends View implements LayoutElement { @@ -222,7 +293,7 @@ namespace pxsim.visuals { }); } - protected buildDom(width: number): SVGElement { + protected buildDom(): SVGElement { return undefined; } } diff --git a/sim/visuals/wireView.ts b/sim/visuals/wireView.ts index df1dd2a6..b37ac2ac 100644 --- a/sim/visuals/wireView.ts +++ b/sim/visuals/wireView.ts @@ -1,11 +1,10 @@ -/// +/// namespace pxsim.visuals { export class WireView extends View implements LayoutElement { private wire: SVGSVGElement; private path: SVGPathElement; - private selected: boolean; private hasDimensions: boolean; protected startX: number; @@ -30,13 +29,13 @@ namespace pxsim.visuals { this.updatePath(); } - buildDom(width: number): SVGElement { + buildDom(): SVGElement { this.wire = svg.elt("svg", { height: "100%", width: "100%" }) as SVGSVGElement; this.path = pxsim.svg.child(this.wire, "path", { 'd': '', 'fill': 'transparent', 'stroke': '#5A5A5A', - 'stroke-width': '3px' + 'stroke-width': '2px' }) as SVGPathElement; this.setSelected(true); return this.wire; @@ -45,8 +44,8 @@ namespace pxsim.visuals { updatePath() { if (!this.hasDimensions) return; const height = this.endY - this.startY; - const quarterHeight = height / 4; - const middleHeight = this.port == 1 || this.port == 2 ? quarterHeight : quarterHeight * 2; + const thirdHeight = height / 3; + const middleHeight = this.port == 1 || this.port == 2 ? thirdHeight : thirdHeight * 2; let d = `M${this.startX} ${this.startY}`; d += ` L${this.startX} ${this.startY + middleHeight}`; d += ` L${this.endX} ${this.startY + middleHeight}`; @@ -79,7 +78,7 @@ namespace pxsim.visuals { } public setSelected(selected: boolean) { - this.selected = selected; + super.setSelected(selected); this.updateOpacity(); } From 0aa41e9a64b9f1ed088b7b5e9a845b883aba7be4 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Sun, 24 Dec 2017 11:59:01 -0800 Subject: [PATCH 02/21] Fix resizing flickering issue, remove flip animation on start, remove the need for a default height and width in the layout engine --- pxtarget.json | 4 +--- sim/visuals/board.ts | 14 +++++--------- sim/visuals/layoutView.ts | 17 ++++++++--------- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/pxtarget.json b/pxtarget.json index ac5ef3f1..64a763e7 100644 --- a/pxtarget.json +++ b/pxtarget.json @@ -139,9 +139,7 @@ }, "monacoColors": { "editor.background": "#ecf6ff" - }, - "simAnimationEnter": "horizontal flip in", - "simAnimationExit": "horizontal flip out" + } }, "ignoreDocsErrors": true } diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index ba68a607..5c3d5146 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -286,18 +286,13 @@ namespace pxsim.visuals { window.addEventListener("resize", e => { this.resize(); }); - - setTimeout(() => { - this.resize(); - }, 200); } public resize() { if (!this.element) return; - const bounds = this.element.getBoundingClientRect(); - this.width = bounds.width; - this.height = bounds.height; - this.layoutView.layout(bounds.width, bounds.height); + this.width = document.body.offsetWidth; + this.height = document.body.offsetHeight; + this.layoutView.layout(this.width, this.height); this.updateState(); let state = ev3board().screenState; @@ -340,6 +335,7 @@ namespace pxsim.visuals { private begin() { this.running = true; + this.updateState(); } private running: boolean = false; @@ -405,7 +401,7 @@ namespace pxsim.visuals { }); let state = ev3board().screenState; - if (!state.didChange()) { + if (state.didChange()) { this.updateScreenStep(state); } } diff --git a/sim/visuals/layoutView.ts b/sim/visuals/layoutView.ts index 5a70217e..49674291 100644 --- a/sim/visuals/layoutView.ts +++ b/sim/visuals/layoutView.ts @@ -3,9 +3,6 @@ /// namespace pxsim.visuals { - export const DEFAULT_WIDTH = 350; - export const DEFAULT_HEIGHT = 700; - export const BRICK_HEIGHT_RATIO = 1 / 3; export const MODULE_AND_WIRING_HEIGHT_RATIO = 1 / 3; // For inputs and outputs @@ -220,8 +217,10 @@ namespace pxsim.visuals { this.offsets = []; - const contentWidth = this.width || DEFAULT_WIDTH; - const contentHeight = this.height || DEFAULT_HEIGHT; + const contentWidth = this.width; + if (!contentWidth) return; + const contentHeight = this.height; + if (!contentHeight) return; const moduleHeight = this.getModuleHeight(); @@ -337,16 +336,16 @@ namespace pxsim.visuals { } public getBrickHeight() { - return (this.height || DEFAULT_HEIGHT) * BRICK_HEIGHT_RATIO; + return this.height * BRICK_HEIGHT_RATIO; } public getWiringHeight() { - return (this.height || DEFAULT_HEIGHT) * WIRING_HEIGHT_RATIO; + return this.height * WIRING_HEIGHT_RATIO; } public getModuleBounds() { return { - width: (this.width || DEFAULT_WIDTH) / 4, + width: this.width / 4, height: this.getModuleHeight() } } @@ -360,7 +359,7 @@ namespace pxsim.visuals { } public getModuleHeight() { - return (this.height || DEFAULT_HEIGHT) * MODULE_HEIGHT_RATIO; + return this.height * MODULE_HEIGHT_RATIO; } } } \ No newline at end of file From c398a5a133cb0ef4da27eb6c050a2bf2276534f2 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Tue, 26 Dec 2017 23:19:04 -0800 Subject: [PATCH 03/21] Update padding and fix wiring order --- sim/visuals/controlView.ts | 2 +- sim/visuals/layoutView.ts | 14 +++++++------- sim/visuals/nodes/colorSensorView.ts | 2 +- sim/visuals/nodes/gyroSensorView.ts | 2 +- sim/visuals/nodes/touchSensorView.ts | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sim/visuals/controlView.ts b/sim/visuals/controlView.ts index 6c9f1dd5..e8fdbc4f 100644 --- a/sim/visuals/controlView.ts +++ b/sim/visuals/controlView.ts @@ -12,6 +12,7 @@ namespace pxsim.visuals { constructor(protected parent: SVGSVGElement, protected globalDefs: SVGDefsElement, protected state: T, protected port: number) { super(state); + } getInnerWidth(): number { @@ -57,7 +58,6 @@ namespace pxsim.visuals { } onComponentVisible() { - } } } \ No newline at end of file diff --git a/sim/visuals/layoutView.ts b/sim/visuals/layoutView.ts index 49674291..962e07e9 100644 --- a/sim/visuals/layoutView.ts +++ b/sim/visuals/layoutView.ts @@ -153,12 +153,6 @@ namespace pxsim.visuals { this.contentGroup = svg.elt("g") as SVGGElement; this.scrollGroup = svg.child(this.contentGroup, "g") as SVGGElement; - // Inject all view containers - for (let i = 0; i < 4; i++) { - this.inputContainers[i].inject(this.scrollGroup); - this.outputContainers[i].inject(this.scrollGroup); - } - this.inputs = []; this.outputs = []; this.inputControls = []; @@ -172,6 +166,12 @@ namespace pxsim.visuals { this.inputWires[port].inject(this.scrollGroup); } + // Inject all view containers + for (let i = 0; i < 4; i++) { + this.inputContainers[i].inject(this.scrollGroup); + this.outputContainers[i].inject(this.scrollGroup); + } + // Inject all ports this.setInput(0, new PortView(0, 'A')); this.setInput(1, new PortView(1, 'B')); @@ -267,7 +267,7 @@ namespace pxsim.visuals { currentY = moduleHeight; const wireBrickSpacing = brickWidth / 5; - const wiringYPadding = 0; + const wiringYPadding = 5; let wireStartX = 0; let wireEndX = brickPadding + wireBrickSpacing; let wireEndY = currentY + this.getWiringHeight() + wiringYPadding; diff --git a/sim/visuals/nodes/colorSensorView.ts b/sim/visuals/nodes/colorSensorView.ts index 6a1dc560..62d82023 100644 --- a/sim/visuals/nodes/colorSensorView.ts +++ b/sim/visuals/nodes/colorSensorView.ts @@ -10,7 +10,7 @@ namespace pxsim.visuals { } public getPaddingRatio() { - return 1 / 6; + return 1 / 4; } public updateState() { diff --git a/sim/visuals/nodes/gyroSensorView.ts b/sim/visuals/nodes/gyroSensorView.ts index 879e3d94..37850463 100644 --- a/sim/visuals/nodes/gyroSensorView.ts +++ b/sim/visuals/nodes/gyroSensorView.ts @@ -8,7 +8,7 @@ namespace pxsim.visuals { } public getPaddingRatio() { - return 1 / 4; + return 0.3; } } } \ No newline at end of file diff --git a/sim/visuals/nodes/touchSensorView.ts b/sim/visuals/nodes/touchSensorView.ts index c86e88e9..78932bdf 100644 --- a/sim/visuals/nodes/touchSensorView.ts +++ b/sim/visuals/nodes/touchSensorView.ts @@ -17,7 +17,7 @@ namespace pxsim.visuals { } public getPaddingRatio() { - return 1 / 10; + return 1 / 4; } public hasClick() { From 85c14bb05abe710483a37922f0f5a8cdefbdcf9e Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Tue, 26 Dec 2017 23:23:26 -0800 Subject: [PATCH 04/21] Fix rotation and distance slider update state --- sim/visuals/controls/distanceSlider.ts | 27 ++++++++------------------ sim/visuals/controls/rotationSlider.ts | 13 +------------ 2 files changed, 9 insertions(+), 31 deletions(-) diff --git a/sim/visuals/controls/distanceSlider.ts b/sim/visuals/controls/distanceSlider.ts index d3b28cce..b6d07ba2 100644 --- a/sim/visuals/controls/distanceSlider.ts +++ b/sim/visuals/controls/distanceSlider.ts @@ -9,18 +9,16 @@ namespace pxsim.visuals { private static SLIDER_HANDLE_HEIGHT = 31; - private isVisible = false; - getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) { let gid = "gradient-slider-" + this.getId(); this.group = svg.elt("g") as SVGGElement; this.gradient = createGradient(gid, this.getGradientDefinition()); - this.gradient.setAttribute('x1', '-438.37'); - this.gradient.setAttribute('y1', '419.43'); - this.gradient.setAttribute('x2', '-438.37'); - this.gradient.setAttribute('y2', '418.43'); - this.gradient.setAttribute('gradientTransform', 'matrix(50, 0, 0, -110, 21949.45, 46137.67)'); - this.gradient.setAttribute('gradientUnits', 'userSpaceOnUse'); + this.gradient.setAttribute('x1', '0%'); + this.gradient.setAttribute('y1', '0%'); + this.gradient.setAttribute('x2', '0%'); + this.gradient.setAttribute('y2', '100%'); + // this.gradient.setAttribute('gradientTransform', 'matrix(50, 0, 0, -110, 21949.45, 46137.67)'); + // this.gradient.setAttribute('gradientUnits', 'userSpaceOnUse'); globalDefs.appendChild(this.gradient); this.group = svg.elt("g") as SVGGElement; @@ -79,7 +77,7 @@ namespace pxsim.visuals { } updateState() { - if (!this.isVisible) { + if (!this.visible) { return; } const node = this.state; @@ -88,15 +86,6 @@ namespace pxsim.visuals { this.slider.setAttribute("transform", `translate(0, ${y - DistanceSliderControl.SLIDER_HANDLE_HEIGHT / 2})`); } - onComponentVisible() { - super.onComponentVisible(); - this.isVisible = true; - } - - onComponentHidden() { - this.isVisible = false; - } - private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) { let cur = svg.cursorPoint(pt, parent, ev); const height = this.getContentHeight(); //DistanceSliderControl.SLIDER_HEIGHT; @@ -119,7 +108,7 @@ namespace pxsim.visuals { return { stops: [ { offset: 0, color: '#626262' }, - { offset: 1, color: "#ddd" } + { offset: 100, color: "#ddd" } ] }; } diff --git a/sim/visuals/controls/rotationSlider.ts b/sim/visuals/controls/rotationSlider.ts index 3858c53a..1a557857 100644 --- a/sim/visuals/controls/rotationSlider.ts +++ b/sim/visuals/controls/rotationSlider.ts @@ -6,8 +6,6 @@ namespace pxsim.visuals { private group: SVGGElement; private slider: SVGGElement; - private isVisible = false; - private static SLIDER_WIDTH = 70; private static SLIDER_HEIGHT = 78; @@ -61,7 +59,7 @@ namespace pxsim.visuals { } updateState() { - if (!this.isVisible) { + if (!this.visible) { return; } const node = this.state; @@ -71,15 +69,6 @@ namespace pxsim.visuals { this.slider.setAttribute("transform", `translate(${x}, ${y})`); } - onComponentVisible() { - super.onComponentVisible(); - this.isVisible = true; - } - - onComponentHidden() { - this.isVisible = false; - } - private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) { let cur = svg.cursorPoint(pt, parent, ev); const width = CONTROL_WIDTH; //DistanceSliderControl.SLIDER_HEIGHT; From 8204995749040b89f7cb96602485a58e8d706fc7 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Tue, 26 Dec 2017 23:28:29 -0800 Subject: [PATCH 05/21] Fix wire view to match spec size of wires. --- sim/visuals/wireView.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sim/visuals/wireView.ts b/sim/visuals/wireView.ts index b37ac2ac..901cf573 100644 --- a/sim/visuals/wireView.ts +++ b/sim/visuals/wireView.ts @@ -35,7 +35,7 @@ namespace pxsim.visuals { 'd': '', 'fill': 'transparent', 'stroke': '#5A5A5A', - 'stroke-width': '2px' + 'stroke-width': '3px' }) as SVGPathElement; this.setSelected(true); return this.wire; From fb31b81f7ea551fe9018e0394e120859b3edfdb1 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 27 Dec 2017 14:48:15 -0800 Subject: [PATCH 06/21] Update motor SVG assets and connections --- sim/visuals/assets/Large Motor.svg | 126 +++++++++++++++------------ sim/visuals/assets/LargeMotorsvg.ts | 126 +++++++++++++++------------ sim/visuals/assets/MediumMotor.svg | 45 +++++----- sim/visuals/assets/MediumMotorsvg.ts | 47 +++++----- sim/visuals/layoutView.ts | 14 +++ sim/visuals/nodes/largeMotorView.ts | 8 +- sim/visuals/nodes/mediumMotorView.ts | 8 +- 7 files changed, 217 insertions(+), 157 deletions(-) diff --git a/sim/visuals/assets/Large Motor.svg b/sim/visuals/assets/Large Motor.svg index 68a857fe..b25fe9ae 100644 --- a/sim/visuals/assets/Large Motor.svg +++ b/sim/visuals/assets/Large Motor.svg @@ -1,69 +1,87 @@ - + - - + + - - + + - - + + Large Motor - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + diff --git a/sim/visuals/assets/LargeMotorsvg.ts b/sim/visuals/assets/LargeMotorsvg.ts index 3e791aac..c38ce09b 100644 --- a/sim/visuals/assets/LargeMotorsvg.ts +++ b/sim/visuals/assets/LargeMotorsvg.ts @@ -1,70 +1,88 @@ namespace pxsim { - export const LARGE_MOTOR_SVG = ` + export const LARGE_MOTOR_SVG = ` - - + + - - + + - - + + Large Motor - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + diff --git a/sim/visuals/assets/MediumMotor.svg b/sim/visuals/assets/MediumMotor.svg index be04262c..0bc67d30 100644 --- a/sim/visuals/assets/MediumMotor.svg +++ b/sim/visuals/assets/MediumMotor.svg @@ -1,28 +1,33 @@ - + - - - + + + MediumMotor - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - diff --git a/sim/visuals/assets/MediumMotorsvg.ts b/sim/visuals/assets/MediumMotorsvg.ts index 32354672..33054802 100644 --- a/sim/visuals/assets/MediumMotorsvg.ts +++ b/sim/visuals/assets/MediumMotorsvg.ts @@ -1,30 +1,35 @@ namespace pxsim.visuals { - export const MEDIUM_MOTOR_SVG = ` + export const MEDIUM_MOTOR_SVG = ` - - - + + + - Medium Motor - - - - - - - + MediumMotor + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - `; } \ No newline at end of file diff --git a/sim/visuals/layoutView.ts b/sim/visuals/layoutView.ts index 962e07e9..b2184303 100644 --- a/sim/visuals/layoutView.ts +++ b/sim/visuals/layoutView.ts @@ -222,6 +222,20 @@ namespace pxsim.visuals { const contentHeight = this.height; if (!contentHeight) return; + const noConnections = this.outputs.concat(this.inputs).filter(m => m.getId() != NodeType.Port).length == 0; + + if (noConnections) { + // No connections render the entire board + this.brick.resize(contentWidth, contentHeight); + this.brick.translate(0, 0); + + // Hide all other connections + this.outputs.concat(this.inputs).forEach(m => m.setVisible(false)); + return; + } else { + this.outputs.concat(this.inputs).forEach(m => m.setVisible(true)); + } + const moduleHeight = this.getModuleHeight(); const brickHeight = this.getBrickHeight(); diff --git a/sim/visuals/nodes/largeMotorView.ts b/sim/visuals/nodes/largeMotorView.ts index 6fb728fe..62ef88c9 100644 --- a/sim/visuals/nodes/largeMotorView.ts +++ b/sim/visuals/nodes/largeMotorView.ts @@ -3,7 +3,7 @@ namespace pxsim.visuals { export class LargeMotorView extends ModuleView implements LayoutElement { - private static ROTATING_ECLIPSE_ID = "1eb2ae58-2419-47d4-86bf-4f26a7f0cf61"; + private static ROTATING_ECLIPSE_ID = "hole"; constructor(port: number) { super(LARGE_MOTOR_SVG, "large-motor", NodeType.LargeMotor, port); @@ -20,14 +20,14 @@ namespace pxsim.visuals { private setMotorAngle(angle: number) { const holeEl = this.content.getElementById(this.normalizeId(LargeMotorView.ROTATING_ECLIPSE_ID)) - const width = 34; - const height = 34; + const width = 125.92; + const height = 37.9; const transform = `rotate(${angle} ${width / 2} ${height / 2})`; holeEl.setAttribute("transform", transform); } getWiringRatio() { - return 0.62; + return 0.37; } } } \ No newline at end of file diff --git a/sim/visuals/nodes/mediumMotorView.ts b/sim/visuals/nodes/mediumMotorView.ts index 10371475..b1f17f3f 100644 --- a/sim/visuals/nodes/mediumMotorView.ts +++ b/sim/visuals/nodes/mediumMotorView.ts @@ -6,7 +6,7 @@ namespace pxsim.visuals { export class MediumMotorView extends ModuleView implements LayoutElement { - private static ROTATING_ECLIPSE_ID = "Hole"; + private static ROTATING_ECLIPSE_ID = "medmotor_Hole"; private hasPreviousAngle: boolean; private previousAngle: number; @@ -30,9 +30,9 @@ namespace pxsim.visuals { private setMotorAngle(angle: number) { const holeEl = this.content.getElementById(this.normalizeId(MediumMotorView.ROTATING_ECLIPSE_ID)) - const width = 47.9; - const height = 47.2; - const transform = `translate(-1.5 -1.49) rotate(${angle} ${width / 2} ${height / 2})`; + const width = 44.45; + const height = 44.45; + const transform = `translate(2 1.84) rotate(${angle} ${width / 2} ${height / 2})`; holeEl.setAttribute("transform", transform); } } From 8be4bb11d895917a6c4714b4b1a2e09f3c8e5e4a Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 27 Dec 2017 16:30:42 -0800 Subject: [PATCH 07/21] Fix resizing in controls to work for all sizes including full screen --- sim/visuals/board.ts | 9 ++++- sim/visuals/controlView.ts | 18 ++++++++-- sim/visuals/controls/colorGrid.ts | 31 +++++++++++------ sim/visuals/controls/colorWheel.ts | 10 +++++- sim/visuals/controls/distanceSlider.ts | 47 ++++++++++++++++++-------- 5 files changed, 85 insertions(+), 30 deletions(-) diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index 5c3d5146..b3f92cc4 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -33,11 +33,18 @@ namespace pxsim.visuals { font-family:"Lucida Console", Monaco, monospace; font-size:8px; fill:#fff; - pointer-events: none; user-select: none; + pointer-events: none; + user-select: none; } .sim-text.small { font-size:6px; } + .sim-text.large { + font-size:30px; + } + .sim-text.number { + font-family: Lato, Work Sans, PT Serif, Source Serif Pro; + } .sim-text.inverted { fill:#000; } diff --git a/sim/visuals/controlView.ts b/sim/visuals/controlView.ts index e8fdbc4f..4bcebe92 100644 --- a/sim/visuals/controlView.ts +++ b/sim/visuals/controlView.ts @@ -5,6 +5,8 @@ namespace pxsim.visuals { export const CONTROL_WIDTH = 87.5; export const CONTROL_HEIGHT = 175; + export const CONTROL_TEXT_COLOR = '#000'; + export abstract class ControlView extends SimView implements LayoutElement { protected content: SVGSVGElement; @@ -36,7 +38,7 @@ namespace pxsim.visuals { } buildDom(): SVGElement { - this.content = svg.elt("svg", { viewBox: `0 0 ${this.getInnerWidth()} ${this.getInnerHeight()}`}) as SVGSVGElement; + this.content = svg.elt("svg", { viewBox: `0 0 ${this.getInnerWidth()} ${this.getInnerHeight()}` }) as SVGSVGElement; this.content.appendChild(this.getInnerView(this.parent, this.globalDefs)); return this.content; } @@ -52,8 +54,18 @@ namespace pxsim.visuals { const currentHeight = this.getInnerHeight(); const newHeight = currentHeight / currentWidth * width; const newWidth = currentWidth / currentHeight * height; - this.content.setAttribute('width', `${width}`); - this.content.setAttribute('height', `${newHeight}`); + if (newHeight > height) { + // scale width instead + this.content.setAttribute('width', `${newWidth}`); + this.content.setAttribute('height', `${height}`); + // translate to the middle (width) + this.translate(width / 2 - newWidth / 2, 0); + } else { + this.content.setAttribute('width', `${width}`); + this.content.setAttribute('height', `${newHeight}`); + // translate to the middle (height) + this.translate(0, height / 2 - newHeight / 2); + } } } diff --git a/sim/visuals/controls/colorGrid.ts b/sim/visuals/controls/colorGrid.ts index c1d6b6fc..ea5823a9 100644 --- a/sim/visuals/controls/colorGrid.ts +++ b/sim/visuals/controls/colorGrid.ts @@ -7,35 +7,46 @@ namespace pxsim.visuals { getInnerView() { this.group = svg.elt("g") as SVGGElement; - this.group.setAttribute("transform", `translate(17, ${20 + this.getHeight() / 4}) scale(5)`) + const innerHeight = 13; + const innerWidth = 11; + this.group.setAttribute("transform", `translate(1.02, 1.5) scale(0.8)`) - const colorIds = ['red', 'yellow', 'blue', 'green', 'black', 'grey']; - const colors = ['#f12a21', '#ffd01b', '#006db3', '#00934b', '#000', '#6c2d00']; + const colorIds = ['red', 'yellow', 'blue', 'green', undefined, 'grey']; + const colors = ['#f12a21', '#ffd01b', '#006db3', '#00934b', undefined, '#6c2d00']; const colorValue = [5, 4, 2, 3, 1, 7]; let cy = -4; for (let c = 0; c < colorIds.length; c++) { const cx = c % 2 == 0 ? 2.2 : 8.2; if (c % 2 == 0) cy += 5; - const circle = pxsim.svg.child(this.group, "circle", { 'class': 'sim-color-grid-circle', 'cx': cx, 'cy': cy, 'r': '2', 'style': `fill: ${colors[c]}` }); - circle.addEventListener(pointerEvents.down, ev => { - this.setColor(colorValue[c]); - }) + if (colorIds[c]) { + const circle = pxsim.svg.child(this.group, "circle", { 'class': 'sim-color-grid-circle', 'cx': cx, 'cy': cy, 'r': '2', 'style': `fill: ${colors[c]}` }); + circle.addEventListener(pointerEvents.down, ev => { + this.setColor(colorValue[c]); + }) + } } const whiteCircleWrapper = pxsim.svg.child(this.group, "g", { 'id': 'white-cirlce-wrapper' }); - pxsim.svg.child(whiteCircleWrapper, "circle", { 'class': 'sim-color-grid-circle', 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: #fff` }); - pxsim.svg.child(whiteCircleWrapper, "circle", { 'cx': 2.2, 'cy': '16', 'r': '2', 'style': `fill: none;stroke: #94989b;stroke-width: 0.5px` }); + pxsim.svg.child(whiteCircleWrapper, "circle", { 'class': 'sim-color-grid-circle', 'cx': 2.2, 'cy': '11', 'r': '2', 'style': `fill: #fff` }); + pxsim.svg.child(whiteCircleWrapper, "circle", { 'cx': 2.2, 'cy': '11', 'r': '2', 'style': `fill: none;stroke: #94989b;stroke-width: 0.1px` }); whiteCircleWrapper.addEventListener(pointerEvents.down, ev => { this.setColor(6); }) return this.group; } + getInnerWidth() { + return 10.2; + } + + getInnerHeight() { + return 15; + } + private setColor(color: number) { const state = this.state; state.setColor(color); } } - } \ No newline at end of file diff --git a/sim/visuals/controls/colorWheel.ts b/sim/visuals/controls/colorWheel.ts index 0d20763f..f0ff4adb 100644 --- a/sim/visuals/controls/colorWheel.ts +++ b/sim/visuals/controls/colorWheel.ts @@ -10,7 +10,7 @@ namespace pxsim.visuals { getInnerView(parent: SVGSVGElement) { this.defs = svg.child(this.element, "defs", {}); this.group = svg.elt("g") as SVGGElement; - this.group.setAttribute("transform", `translate(12, ${this.getHeight() / 2 - 15}) scale(2)`) + this.group.setAttribute("transform", `translate(12, 0) scale(2)`) let gc = "gradient-color"; this.colorGradient = svg.linearGradient(this.defs, gc, true); @@ -53,6 +53,14 @@ namespace pxsim.visuals { return this.group; } + getInnerWidth() { + return CONTROL_WIDTH; + } + + getInnerHeight() { + return CONTROL_WIDTH; + } + updateState() { if (!this.visible) { return; diff --git a/sim/visuals/controls/distanceSlider.ts b/sim/visuals/controls/distanceSlider.ts index b6d07ba2..a4542ab6 100644 --- a/sim/visuals/controls/distanceSlider.ts +++ b/sim/visuals/controls/distanceSlider.ts @@ -7,7 +7,10 @@ namespace pxsim.visuals { private gradient: SVGLinearGradientElement; private slider: SVGGElement; - private static SLIDER_HANDLE_HEIGHT = 31; + private reporter: SVGTextElement; + + private static SLIDER_HANDLE_HEIGHT = 26; + private static SLIDER_SIDE_PADDING = 6; getInnerView(parent: SVGSVGElement, globalDefs: SVGDefsElement) { let gid = "gradient-slider-" + this.getId(); @@ -23,15 +26,19 @@ namespace pxsim.visuals { this.group = svg.elt("g") as SVGGElement; - const sliderGroup = pxsim.svg.child(this.group, "g"); - sliderGroup.setAttribute("transform", `translate(0, ${10 + this.getTopPadding()})`) + const reporterGroup = pxsim.svg.child(this.group, "g"); + reporterGroup.setAttribute("transform", `translate(31, 42)`); + this.reporter = pxsim.svg.child(reporterGroup, "text", { 'x': 0, 'y': '0', 'class': 'sim-text number large inverted' }) as SVGTextElement; - const rect = pxsim.svg.child(sliderGroup, "rect", { 'x': this.getLeftPadding(), 'y': 2, 'width': this.getWidth() - this.getLeftPadding() * 2, 'height': this.getContentHeight(), 'style': `fill: url(#${gid})` }); + const sliderGroup = pxsim.svg.child(this.group, "g"); + sliderGroup.setAttribute("transform", `translate(${this.getWidth() / 2 - this.getSliderWidth() / 2}, ${this.getReporterHeight()})`) + + const rect = pxsim.svg.child(sliderGroup, "rect", { 'x': DistanceSliderControl.SLIDER_SIDE_PADDING, 'y': 2, 'width': this.getSliderWidth() - DistanceSliderControl.SLIDER_SIDE_PADDING * 2, 'height': this.getSliderHeight(), 'style': `fill: url(#${gid})` }); this.slider = pxsim.svg.child(sliderGroup, "g", { "transform": "translate(0,0)" }) as SVGGElement; const sliderInner = pxsim.svg.child(this.slider, "g"); - pxsim.svg.child(sliderInner, "rect", { 'width': this.getWidth(), 'height': DistanceSliderControl.SLIDER_HANDLE_HEIGHT, 'rx': '2', 'ry': '2', 'style': 'fill: #f12a21' }); - pxsim.svg.child(sliderInner, "rect", { 'x': '0.5', 'y': '0.5', 'width': this.getWidth() - 1, 'height': DistanceSliderControl.SLIDER_HANDLE_HEIGHT - 1, 'rx': '1.5', 'ry': '1.5', 'style': 'fill: none;stroke: #b32e29' }); + pxsim.svg.child(sliderInner, "rect", { 'width': this.getSliderWidth(), 'height': DistanceSliderControl.SLIDER_HANDLE_HEIGHT, 'rx': '2', 'ry': '2', 'style': 'fill: #f12a21' }); + pxsim.svg.child(sliderInner, "rect", { 'x': '0.5', 'y': '0.5', 'width': this.getSliderWidth() - 1, 'height': DistanceSliderControl.SLIDER_HANDLE_HEIGHT - 1, 'rx': '1.5', 'ry': '1.5', 'style': 'fill: none;stroke: #b32e29' }); const dragSurface = svg.child(this.group, "rect", { x: 0, @@ -64,16 +71,24 @@ namespace pxsim.visuals { return this.group; } - private getLeftPadding() { - return this.getInnerWidth() * 0.12; + getInnerHeight() { + return 192; } - private getTopPadding() { - return this.getInnerHeight() / 4; + getInnerWidth() { + return 111; } - private getContentHeight() { - return this.getInnerHeight() * 0.6; + private getReporterHeight() { + return 50; + } + + private getSliderHeight() { + return 110; + } + + private getSliderWidth() { + return 62; } updateState() { @@ -82,15 +97,17 @@ namespace pxsim.visuals { } const node = this.state; const percentage = node.getValue() / 10; /* convert back to cm */ - const y = this.getContentHeight() * percentage / this.getMax(); + const y = this.getSliderHeight() * percentage / this.getMax(); this.slider.setAttribute("transform", `translate(0, ${y - DistanceSliderControl.SLIDER_HANDLE_HEIGHT / 2})`); + // Update reporter text + this.reporter.textContent = `${parseFloat((percentage).toString()).toFixed(0)}`; } private updateSliderValue(pt: SVGPoint, parent: SVGSVGElement, ev: MouseEvent) { let cur = svg.cursorPoint(pt, parent, ev); - const height = this.getContentHeight(); //DistanceSliderControl.SLIDER_HEIGHT; + const height = this.getSliderHeight(); const bBox = this.content.getBoundingClientRect(); - let t = Math.max(0, Math.min(1, (this.getTopPadding() + height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height)) + let t = Math.max(0, Math.min(1, (DistanceSliderControl.SLIDER_HANDLE_HEIGHT + height + bBox.top / this.scaleFactor - cur.y / this.scaleFactor) / height)) const state = this.state; state.setDistance((1 - t) * (this.getMax())); From f01370e4fda6786faf3ca292584513eb59d76b2b Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Wed, 27 Dec 2017 17:05:15 -0800 Subject: [PATCH 08/21] Simulator support for motor commands (#137) * support for "step" functions * locale files * enum issue * fixing decoding of array * implement clear count * log unknown commands --- sim/dalboard.ts | 8 +-- sim/state/motors.ts | 140 +++++++++++++++++++++++++++----------------- sim/state/output.ts | 35 +++++++---- 3 files changed, 113 insertions(+), 70 deletions(-) diff --git a/sim/dalboard.ts b/sim/dalboard.ts index b542acb0..608d2443 100644 --- a/sim/dalboard.ts +++ b/sim/dalboard.ts @@ -118,10 +118,8 @@ namespace pxsim { getMotor(port: number, large?: boolean): MotorNode[] { if (port == 0xFF) return this.getMotors(); // Return all motors const motorPort = this.motorMap[port]; - if (this.outputNodes[motorPort] == undefined) { - this.outputNodes[motorPort] = large ? - new LargeMotorNode(motorPort) : new MediumMotorNode(motorPort); - } + if (!this.outputNodes[motorPort]) + this.outputNodes[motorPort] = new MotorNode(motorPort, large); return [this.outputNodes[motorPort]]; } @@ -130,7 +128,7 @@ namespace pxsim { } getSensor(port: number, type: number): SensorNode { - if (this.inputNodes[port] == undefined) { + if (!this.inputNodes[port]) { switch (type) { case DAL.DEVICE_TYPE_GYRO: this.inputNodes[port] = new GyroSensorNode(port); break; case DAL.DEVICE_TYPE_COLOR: this.inputNodes[port] = new ColorSensorNode(port); break; diff --git a/sim/state/motors.ts b/sim/state/motors.ts index 8abb3c75..79a6bd18 100644 --- a/sim/state/motors.ts +++ b/sim/state/motors.ts @@ -1,88 +1,122 @@ namespace pxsim { - export abstract class MotorNode extends BaseNode { + export class MotorNode extends BaseNode { isOutput = true; - - protected angle: number = 0; - private rotationsPerMilliSecond: number; - private speed: number; - private large: boolean; - private rotation: number; + + // current state + private angle: number = 0; + private tacho: number = 0; + private speed: number = 0; + private polarity: boolean; + private started: boolean; + private speedCmd: DAL; + private speedCmdValues: number[]; + private speedCmdTacho: number; + private speedCmdTime: number; - constructor(port: number, rpm: number) { + constructor(port: number, large: boolean) { super(port); - this.rotationsPerMilliSecond = rpm / 60000; - } - - setSpeed(speed: number) { - if (this.speed != speed) { - this.speed = speed; - this.changed = true; - this.setChangedState(); - } - } - - setLarge(large: boolean) { - this.large = large; + this.setLarge(large); } getSpeed() { return this.speed; } - stepSpeed(speed: number, angle: number, brake: boolean) { - // TODO: implement + getAngle() { + return this.angle; + } + + setSpeedCmd(cmd: DAL, values: number[]) { + this.speedCmd = cmd; + this.speedCmdValues = values; + this.speedCmdTacho = this.angle; + this.speedCmdTime = pxsim.U.now(); + } + + clearSpeedCmd() { + delete this.speedCmd; + } + + setLarge(large: boolean) { + this.id = large ? NodeType.LargeMotor : NodeType.MediumMotor; + this.rotationsPerMilliSecond = (large ? 170 : 250) / 60000; } setPolarity(polarity: number) { // Either 1 or 255 (reverse) this.polarity = polarity === 255; - // TODO: implement } reset() { - // TODO: implement + // not sure what reset does... + } + + clearCount() { + this.tacho = 0; + this.angle = 0; } stop() { - // TODO: implement - this.setSpeed(0); + this.started = false; } start() { - // TODO: implement - this.setChangedState(); - } - - public getAngle() { - return this.angle; + this.started = true; } updateState(elapsed: number) { - const rotations = this.getSpeed() / 100 * this.rotationsPerMilliSecond * elapsed; - const angle = rotations * 360; - if (angle) { - this.angle += angle; + // compute new speed + switch (this.speedCmd) { + case DAL.opOutputSpeed: + case DAL.opOutputPower: + // assume power == speed + // TODO: PID + this.speed = this.speedCmdValues[0]; + break; + case DAL.opOutputTimeSpeed: + case DAL.opOutputTimePower: + case DAL.opOutputStepPower: + case DAL.opOutputStepSpeed: + // ramp up, run, ramp down, using time + const speed = this.speedCmdValues[0]; + const step1 = this.speedCmdValues[1]; + const step2 = this.speedCmdValues[2]; + const step3 = this.speedCmdValues[3]; + const brake = this.speedCmdValues[4]; + const dstep = (this.speedCmd == DAL.opOutputTimePower || this.speedCmd == DAL.opOutputTimeSpeed) + ? pxsim.U.now() - this.speedCmdTime + : this.tacho - this.speedCmdTacho; + if (dstep < step1) // rampup + this.speed = speed * dstep / step1; + else if (dstep < step1 + step2) // run + this.speed = speed; + else if (dstep < step1 + step2 + step3) + this.speed = speed * (step1 + step2 + step3 - dstep) / (step1 + step2 + step3); + else { + if (brake) this.speed = 0; + this.clearSpeedCmd(); + } + break; + } + + // compute delta angle + const rotations = this.speed / 100 * this.rotationsPerMilliSecond * elapsed; + const deltaAngle = rotations * 360; + if (deltaAngle) { + this.angle += deltaAngle; + this.tacho += Math.abs(deltaAngle); this.setChangedState(); } + + // if the motor was stopped or there are no speed commands, + // let it coast to speed 0 + if (this.speed && (!this.started || !this.speedCmd)) { + // decay speed 5% per tick + this.speed = Math.max(0, Math.abs(this.speed) - 5) * Math.sign(this.speed); + } } } - - export class MediumMotorNode extends MotorNode { - id = NodeType.MediumMotor; - - constructor(port: number) { - super(port, 250); - } - } - - export class LargeMotorNode extends MotorNode { - id = NodeType.LargeMotor; - - constructor(port: number) { - super(port, 170); - } - } } \ No newline at end of file diff --git a/sim/state/output.ts b/sim/state/output.ts index a3b93f8e..53d9f420 100644 --- a/sim/state/output.ts +++ b/sim/state/output.ts @@ -34,24 +34,32 @@ namespace pxsim { motors.forEach(motor => motor.reset()); return 2; } - case DAL.opOutputStepSpeed: { + case DAL.opOutputClearCount: + const port = buf.data[1]; + const motors = ev3board().getMotor(port); + motors.forEach(motor => motor.clearCount()); + break; + case DAL.opOutputStepPower: + case DAL.opOutputStepSpeed: + case DAL.opOutputTimePower: + case DAL.opOutputTimeSpeed: { // step speed const port = buf.data[1]; - const speed = buf.data[2] << 24 >> 24; // signed byte - // note that b[3] is padding - const step1 = buf.data[4]; - const step2 = buf.data[5]; // angle - const step3 = buf.data[6]; - const brake = buf.data[7]; + const speed = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int8LE, 2); // signed byte + // note that b[3] is padding + const step1 = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int32LE, 4); + const step2 = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int32LE, 8); + const step3 = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int32LE, 12); + const brake = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int8LE, 16); //console.log(buf); const motors = ev3board().getMotor(port); - motors.forEach(motor => motor.stepSpeed(speed, step2, brake === 1)); + motors.forEach(motor => motor.setSpeedCmd(cmd, [speed, step1, step2, step3, brake])); return 2; } case DAL.opOutputStop: { // stop const port = buf.data[1]; - const brake = buf.data[2]; + const brake = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int8LE, 2); const motors = ev3board().getMotor(port); motors.forEach(motor => motor.stop()); return 2; @@ -59,9 +67,9 @@ namespace pxsim { case DAL.opOutputSpeed: { // setSpeed const port = buf.data[1]; - const speed = buf.data[2] << 24 >> 24; // signed byte + const speed = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int8LE, 2); const motors = ev3board().getMotor(port); - motors.forEach(motor => motor.setSpeed(speed)); + motors.forEach(motor => motor.setSpeedCmd(cmd, [speed])); return 2; } case DAL.opOutputStart: { @@ -74,7 +82,7 @@ namespace pxsim { case DAL.opOutputPolarity: { // reverse const port = buf.data[1]; - const polarity = buf.data[2]; + const polarity = pxsim.BufferMethods.getNumber(buf, BufferMethods.NumberFormat.Int8LE, 2); const motors = ev3board().getMotor(port); motors.forEach(motor => motor.setPolarity(polarity)); return 2; @@ -86,6 +94,9 @@ namespace pxsim { motors.forEach(motor => motor.setLarge(large)); return 2; } + default: + console.warn('unknown cmd: ' + cmd); + break; } console.log("pwm write"); From 0da175a8cd552202c4981dc8da7fb3b69367126e Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 27 Dec 2017 17:06:23 -0800 Subject: [PATCH 09/21] Add motor reporter control --- sim/visuals/board.ts | 6 ++-- sim/visuals/controls/colorGrid.ts | 2 -- sim/visuals/controls/motorReporter.ts | 51 +++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 sim/visuals/controls/motorReporter.ts diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index b3f92cc4..7d6b2ed4 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -212,9 +212,9 @@ namespace pxsim.visuals { } case NodeType.MediumMotor: case NodeType.LargeMotor: { - // const state = ev3board().getMotor(port)[0]; - // view = new MotorInputControl(this.element, this.defs, state, port); - // break; + const state = ev3board().getMotors()[port]; + view = new MotorReporterControl(this.element, this.defs, state, port); + break; } } diff --git a/sim/visuals/controls/colorGrid.ts b/sim/visuals/controls/colorGrid.ts index ea5823a9..df89cfc8 100644 --- a/sim/visuals/controls/colorGrid.ts +++ b/sim/visuals/controls/colorGrid.ts @@ -7,8 +7,6 @@ namespace pxsim.visuals { getInnerView() { this.group = svg.elt("g") as SVGGElement; - const innerHeight = 13; - const innerWidth = 11; this.group.setAttribute("transform", `translate(1.02, 1.5) scale(0.8)`) const colorIds = ['red', 'yellow', 'blue', 'green', undefined, 'grey']; diff --git a/sim/visuals/controls/motorReporter.ts b/sim/visuals/controls/motorReporter.ts new file mode 100644 index 00000000..b6c2fc3b --- /dev/null +++ b/sim/visuals/controls/motorReporter.ts @@ -0,0 +1,51 @@ + + +namespace pxsim.visuals { + + export class MotorReporterControl extends ControlView { + private group: SVGGElement; + + private circleBar: SVGCircleElement; + + private reporter: SVGTextElement; + + getInnerView() { + this.group = svg.elt("g") as SVGGElement; + + const outerCircle = pxsim.svg.child(this.group, "circle", { 'stroke-dasharray': '565.48', 'stroke-dashoffset': '0', 'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 1s linear;`, 'stroke': '#a8aaa8', 'stroke-width': '1rem' }) as SVGCircleElement; + this.circleBar = pxsim.svg.child(this.group, "circle", { 'stroke-dasharray': '565.48', 'stroke-dashoffset': '0', 'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 1s linear;`, 'stroke': '#f12a21', 'stroke-width': '1rem' }) as SVGCircleElement; + + this.reporter = pxsim.svg.child(this.group, "text", { 'x': this.getWidth() / 2, 'y': this.getHeight() / 2, 'text-anchor': 'middle', 'style': 'font-size: 50px', 'class': 'sim-text inverted number' }) as SVGTextElement; + + return this.group; + } + + getInnerWidth() { + return 200; + } + + getInnerHeight() { + return 200; + } + + updateState() { + if (!this.visible) { + return; + } + const node = this.state; + const speed = node.getSpeed(); + this.updateSpeed(speed); + + // Update reporter + this.reporter.textContent = `${speed}`; + } + + private updateSpeed(speed: number) { + let c = Math.PI * (90 * 2); + if (speed < 0) speed = 100 - speed; + + let pct = ((100 - speed) / 100) * c; + this.circleBar.setAttribute('stroke-dashoffset', `${pct}`); + } + } +} \ No newline at end of file From 2fb75a2d83154a19a928d4931fc2f1fedbb924d7 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 27 Dec 2017 17:07:50 -0800 Subject: [PATCH 10/21] Added todo --- sim/visuals/board.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index 7d6b2ed4..b90e47fd 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -212,6 +212,7 @@ namespace pxsim.visuals { } case NodeType.MediumMotor: case NodeType.LargeMotor: { + // TODO: figure out if the motor is in "input" or "output" mode const state = ev3board().getMotors()[port]; view = new MotorReporterControl(this.element, this.defs, state, port); break; From 7e2251d8acf907d905b1384e5c86b63be85f0377 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 27 Dec 2017 20:35:36 -0800 Subject: [PATCH 11/21] Fix negative motor reporting --- sim/visuals/controls/motorReporter.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sim/visuals/controls/motorReporter.ts b/sim/visuals/controls/motorReporter.ts index b6c2fc3b..624fe6de 100644 --- a/sim/visuals/controls/motorReporter.ts +++ b/sim/visuals/controls/motorReporter.ts @@ -42,8 +42,7 @@ namespace pxsim.visuals { private updateSpeed(speed: number) { let c = Math.PI * (90 * 2); - if (speed < 0) speed = 100 - speed; - + speed = Math.abs(speed); let pct = ((100 - speed) / 100) * c; this.circleBar.setAttribute('stroke-dashoffset', `${pct}`); } From a9a9a898111950bfc55f5e72316de9f6526054b7 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 27 Dec 2017 20:43:39 -0800 Subject: [PATCH 12/21] Better fonts and better alignment of motor reporter control --- sim/visuals/board.ts | 5 +++-- sim/visuals/controls/motorReporter.ts | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index b90e47fd..cdb6fa9b 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -43,10 +43,11 @@ namespace pxsim.visuals { font-size:30px; } .sim-text.number { - font-family: Lato, Work Sans, PT Serif, Source Serif Pro; + font-family: Courier, Lato, Work Sans, PT Serif, Source Serif Pro; + font-weight: bold; } .sim-text.inverted { - fill:#000; + fill:#5A5A5A; } /* Color Grid */ diff --git a/sim/visuals/controls/motorReporter.ts b/sim/visuals/controls/motorReporter.ts index 624fe6de..e8a2a048 100644 --- a/sim/visuals/controls/motorReporter.ts +++ b/sim/visuals/controls/motorReporter.ts @@ -12,10 +12,20 @@ namespace pxsim.visuals { getInnerView() { this.group = svg.elt("g") as SVGGElement; - const outerCircle = pxsim.svg.child(this.group, "circle", { 'stroke-dasharray': '565.48', 'stroke-dashoffset': '0', 'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 1s linear;`, 'stroke': '#a8aaa8', 'stroke-width': '1rem' }) as SVGCircleElement; - this.circleBar = pxsim.svg.child(this.group, "circle", { 'stroke-dasharray': '565.48', 'stroke-dashoffset': '0', 'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 1s linear;`, 'stroke': '#f12a21', 'stroke-width': '1rem' }) as SVGCircleElement; + const outerCircle = pxsim.svg.child(this.group, "circle", { + 'stroke-dasharray': '565.48', 'stroke-dashoffset': '0', + 'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 1s linear;`, + 'stroke': '#a8aaa8', 'stroke-width': '1rem' }) as SVGCircleElement; + this.circleBar = pxsim.svg.child(this.group, "circle", { + 'stroke-dasharray': '565.48', 'stroke-dashoffset': '0', + 'cx': 100, 'cy': 100, 'r': '90', 'style': `fill:transparent; transition: stroke-dashoffset 1s linear;`, + 'stroke': '#f12a21', 'stroke-width': '1rem' }) as SVGCircleElement; - this.reporter = pxsim.svg.child(this.group, "text", { 'x': this.getWidth() / 2, 'y': this.getHeight() / 2, 'text-anchor': 'middle', 'style': 'font-size: 50px', 'class': 'sim-text inverted number' }) as SVGTextElement; + this.reporter = pxsim.svg.child(this.group, "text", { + 'x': this.getWidth() / 2, 'y': this.getHeight() / 2, + 'text-anchor': 'middle', 'alignment-baseline': 'middle', + 'style': 'font-size: 50px', + 'class': 'sim-text inverted number' }) as SVGTextElement; return this.group; } From 01f7fe633c2ed52cda0ba9b0cc16ff12561f8d8a Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Thu, 28 Dec 2017 09:07:57 -0800 Subject: [PATCH 13/21] Motorworks2 (#141) * fixing polarity * allocate motor on motorUsed only * perform sub-step integration step for better precision --- sim/dalboard.ts | 27 ++++++++++++++++++---- sim/state/input.ts | 6 ++--- sim/state/motor.ts | 4 ++-- sim/state/{motors.ts => motornode.ts} | 33 +++++++++++++++++++++------ sim/visuals/board.ts | 4 ++-- 5 files changed, 55 insertions(+), 19 deletions(-) rename sim/state/{motors.ts => motornode.ts} (73%) diff --git a/sim/dalboard.ts b/sim/dalboard.ts index 608d2443..4e613d9e 100644 --- a/sim/dalboard.ts +++ b/sim/dalboard.ts @@ -115,12 +115,29 @@ namespace pxsim { return this.brickNode; } + motorUsed(port:number, large: boolean) { + for(let i = 0; i < DAL.NUM_OUTPUTS; ++i) { + const p = 1 << i; + if (port & p) { + const motorPort = this.motorMap[p]; + if (!this.outputNodes[motorPort]) + this.outputNodes[motorPort] = new MotorNode(motorPort, large); + } + } + } + getMotor(port: number, large?: boolean): MotorNode[] { - if (port == 0xFF) return this.getMotors(); // Return all motors - const motorPort = this.motorMap[port]; - if (!this.outputNodes[motorPort]) - this.outputNodes[motorPort] = new MotorNode(motorPort, large); - return [this.outputNodes[motorPort]]; + const r = []; + for(let i = 0; i < DAL.NUM_OUTPUTS; ++i) { + const p = 1 << i; + if (port & p) { + const motorPort = this.motorMap[p]; + const outputNode = this.outputNodes[motorPort]; + if (outputNode) + r.push(outputNode); + } + } + return r; } getMotors() { diff --git a/sim/state/input.ts b/sim/state/input.ts index a00ceec2..1f62e95e 100644 --- a/sim/state/input.ts +++ b/sim/state/input.ts @@ -2,8 +2,8 @@ namespace pxsim.motors { export function __motorUsed(port: number, large: boolean) { - console.log("MOTOR INIT " + port); - const motors = ev3board().getMotor(port, large); + //console.log("MOTOR INIT " + port); + ev3board().motorUsed(port, large); runtime.queueDisplayUpdate(); } } @@ -11,7 +11,7 @@ namespace pxsim.motors { namespace pxsim.sensors { export function __sensorUsed(port: number, type: number) { - console.log("SENSOR INIT " + port + ", type: " + type); + //console.log("SENSOR INIT " + port + ", type: " + type); const sensor = ev3board().getSensor(port, type); runtime.queueDisplayUpdate(); } diff --git a/sim/state/motor.ts b/sim/state/motor.ts index fffab968..308d2197 100644 --- a/sim/state/motor.ts +++ b/sim/state/motor.ts @@ -19,8 +19,8 @@ namespace pxsim { // console.log("motor before read"); for (let port = 0; port < DAL.NUM_OUTPUTS; ++port) { const output = outputs[port]; - const speed = output ? Math.round(outputs[port].getSpeed()) : 0; - const angle = output ? Math.round(outputs[port].getAngle()) : 0; + const speed = output ? outputs[port].getSpeed() : 0; + const angle = output ? outputs[port].getAngle() : 0; const tci = MotorDataOff.TachoCounts + port * MotorDataOff.Size; const tsi = MotorDataOff.TachoSensor + port * MotorDataOff.Size; data[tci] = data[tci + 1] = data[tci + 2] = data[tci + 3] = 0; // Tacho count diff --git a/sim/state/motors.ts b/sim/state/motornode.ts similarity index 73% rename from sim/state/motors.ts rename to sim/state/motornode.ts index 79a6bd18..5676eae6 100644 --- a/sim/state/motors.ts +++ b/sim/state/motornode.ts @@ -8,8 +8,8 @@ namespace pxsim { private angle: number = 0; private tacho: number = 0; private speed: number = 0; + private polarity: number = 1; // -1, 1 or -1 - private polarity: boolean; private started: boolean; private speedCmd: DAL; private speedCmdValues: number[]; @@ -22,7 +22,7 @@ namespace pxsim { } getSpeed() { - return this.speed; + return this.speed * (this.polarity == 0 ? -1 : 1); } getAngle() { @@ -42,12 +42,18 @@ namespace pxsim { setLarge(large: boolean) { this.id = large ? NodeType.LargeMotor : NodeType.MediumMotor; + // large 170 rpm (https://education.lego.com/en-us/products/ev3-large-servo-motor/45502) this.rotationsPerMilliSecond = (large ? 170 : 250) / 60000; } setPolarity(polarity: number) { // Either 1 or 255 (reverse) - this.polarity = polarity === 255; + /* + -1 : Motor will run backward + 0 : Motor will run opposite direction + 1 : Motor will run forward + */ + this.polarity = polarity; } reset() { @@ -68,6 +74,18 @@ namespace pxsim { } updateState(elapsed: number) { + console.log(`motor: ${elapsed}ms - ${this.speed}% - ${this.angle}> - ${this.tacho}|`) + const interval = Math.min(20, elapsed); + let t = 0; + while(t < elapsed) { + let dt = interval; + if (t + dt > elapsed) dt = elapsed - t; + this.updateStateStep(dt); + t += dt; + } + } + + private updateStateStep(elapsed: number) { // compute new speed switch (this.speedCmd) { case DAL.opOutputSpeed: @@ -99,12 +117,13 @@ namespace pxsim { if (brake) this.speed = 0; this.clearSpeedCmd(); } + this.speed = Math.round(this.speed); // integer only break; } // compute delta angle - const rotations = this.speed / 100 * this.rotationsPerMilliSecond * elapsed; - const deltaAngle = rotations * 360; + const rotations = this.getSpeed() / 100 * this.rotationsPerMilliSecond * elapsed; + const deltaAngle = Math.round(rotations * 360); if (deltaAngle) { this.angle += deltaAngle; this.tacho += Math.abs(deltaAngle); @@ -113,9 +132,9 @@ namespace pxsim { // if the motor was stopped or there are no speed commands, // let it coast to speed 0 - if (this.speed && (!this.started || !this.speedCmd)) { + if (this.speed && !(this.started || this.speedCmd)) { // decay speed 5% per tick - this.speed = Math.max(0, Math.abs(this.speed) - 5) * Math.sign(this.speed); + this.speed = Math.round(Math.max(0, Math.abs(this.speed) - 10) * Math.sign(this.speed)); } } } diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index cdb6fa9b..e598839e 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -358,14 +358,14 @@ namespace pxsim.visuals { if (!this.running) return; const fps = GAME_LOOP_FPS; let now; - let then = Date.now(); + let then = pxsim.U.now(); let interval = 1000 / fps; let delta; let that = this; function loop() { const animationId = requestAnimationFrame(loop); that.lastAnimationIds.push(animationId); - now = Date.now(); + now = pxsim.U.now(); delta = now - then; if (delta > interval) { then = now; From 58384017f2990f52292b6279a9aa958d58a8c84e Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Thu, 28 Dec 2017 09:08:27 -0800 Subject: [PATCH 14/21] 0.0.46 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1d418da4..4e6cecef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pxt-ev3", - "version": "0.0.45", + "version": "0.0.46", "description": "LEGO Mindstorms EV3 for Microsoft MakeCode", "private": true, "keywords": [ From d7f46c0fb509e9e667e3f64c7917dd3e403bb509 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Thu, 28 Dec 2017 11:15:53 -0800 Subject: [PATCH 15/21] Hide screen picker properly from typescript --- libs/core/_locales/core-jsdoc-strings.json | 2 - libs/core/_locales/core-strings.json | 1 - libs/core/images.ts | 258 ++++++++++----------- libs/core/screen.ts | 2 +- 4 files changed, 130 insertions(+), 133 deletions(-) diff --git a/libs/core/_locales/core-jsdoc-strings.json b/libs/core/_locales/core-jsdoc-strings.json index 309c14dd..faf6ef75 100644 --- a/libs/core/_locales/core-jsdoc-strings.json +++ b/libs/core/_locales/core-jsdoc-strings.json @@ -21,8 +21,6 @@ "brick.Button.pauseUntil": "Waits until the event is raised", "brick.Button.pauseUntil|param|ev": "the event to wait for", "brick.Button.wasPressed": "See if the button was pressed again since the last time you checked.", - "brick._imagePicker": "An image", - "brick._imagePicker|param|image": "the image", "brick.buttonDown": "Down button on the EV3 Brick.", "brick.buttonEnter": "Enter button on the EV3 Brick.", "brick.buttonLeft": "Left button on the EV3 Brick.", diff --git a/libs/core/_locales/core-strings.json b/libs/core/_locales/core-strings.json index a68e8a47..6e94110a 100644 --- a/libs/core/_locales/core-strings.json +++ b/libs/core/_locales/core-strings.json @@ -28,7 +28,6 @@ "brick.Button.onEvent|block": "on %button|%event", "brick.Button.pauseUntil|block": "pause until %button|%event", "brick.Button.wasPressed|block": "%button|was pressed", - "brick._imagePicker|block": "%image", "brick.buttonDown|block": "down", "brick.buttonEnter|block": "enter", "brick.buttonLeft|block": "left", diff --git a/libs/core/images.ts b/libs/core/images.ts index 5e4d482b..999cb197 100644 --- a/libs/core/images.ts +++ b/libs/core/images.ts @@ -1,260 +1,260 @@ namespace images { - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsBigSmile = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsHeartLarge = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsHeartSmall = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsMouth1open = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsMouth1shut = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsMouth2open = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsMouth2shut = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsSad = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsSick = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsSmile = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsSwearing = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsTalking = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsWink = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const expressionsZzz = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesAngry = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesAwake = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesBlackEye = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesBottomLeft = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesBottomRight = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesCrazy1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesCrazy2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesDisappointed = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesDizzy = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesDown = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesEvil = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesHurt = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesKnockedOut = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesLove = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesMiddleLeft = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesMiddleRight = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesNeutral = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesNuclear = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesPinchLeft = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesPinchMiddle = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesPinchRight = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesSleeping = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesTear = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesTiredLeft = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesTiredMiddle = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesTiredRight = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesToxic = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesUp = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const eyesWinking = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationAccept = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationBackward = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationDecline = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationForward = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationLeft = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationNoGo = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationQuestionMark = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationRight = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationStop1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationStop2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationThumbsDown = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationThumbsUp = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const informationWarning = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoColorSensor = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoEv3icon = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoEv3 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoGyroSensor = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoIrBeacon = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoIrSensor = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoLego = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoLargeMotor = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoMindstorms = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoMediumMotor = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoSoundSensor = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoTempSensor = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoTouchSensor = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const legoUsSensor = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsBomb = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsBoom = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsFire = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsFlowers = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsForest = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsLightOff = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsLightOn = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsLightning = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsNight = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsPirate = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsSnow = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const objectsTarget = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressBar0 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressBar1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressBar2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressBar3 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressBar4 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressDial0 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressDial1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressDial2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressDial3 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressDial4 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressDots0 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressDots1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressDots2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressDots3 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressHourglass0 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressHourglass1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressHourglass2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressTimer0 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressTimer1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressTimer2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressTimer3 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressTimer4 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressWaterLevel0 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressWaterLevel1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressWaterLevel2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const progressWaterLevel3 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemAccept1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemAccept2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemAlert = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemBox = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemBusy0 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemBusy1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemDecline1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemDecline2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemDotEmpty = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemDotFull = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemEv3small = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemPlay = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemSlider0 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemSlider1 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemSlider2 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemSlider3 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemSlider4 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemSlider5 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemSlider6 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemSlider7 = screen.unpackPNG(hex``); - //% fixedInstance jres blockIdentity=brick._imagePicker + //% fixedInstance jres blockIdentity=brick.__imagePicker export const systemSlider8 = screen.unpackPNG(hex``); } diff --git a/libs/core/screen.ts b/libs/core/screen.ts index 9027f5f7..f70dc6e1 100644 --- a/libs/core/screen.ts +++ b/libs/core/screen.ts @@ -158,7 +158,7 @@ namespace brick { //% image.fieldOptions.columns=6 //% image.fieldOptions.hasSearchBar=true //% group="Screen" weight=0 blockHidden=1 - export function _imagePicker(image: Image): Image { + export function __imagePicker(image: Image): Image { return image; } From f30eac41e92c7c0cee6173a06d55a9c6e554dbd4 Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Thu, 28 Dec 2017 11:17:18 -0800 Subject: [PATCH 16/21] Persist selected state of controls across simulator restarts --- sim/state/control.ts | 1 - sim/visuals/board.ts | 30 ++++++++++++++++++++++++++-- sim/visuals/nodes/colorSensorView.ts | 1 + sim/visuals/nodes/largeMotorView.ts | 1 + sim/visuals/nodes/mediumMotorView.ts | 1 + sim/visuals/nodes/moduleView.ts | 18 +++++++++++------ sim/visuals/view.ts | 1 - 7 files changed, 43 insertions(+), 10 deletions(-) diff --git a/sim/state/control.ts b/sim/state/control.ts index dabc588b..0735c5b3 100644 --- a/sim/state/control.ts +++ b/sim/state/control.ts @@ -81,7 +81,6 @@ namespace pxsim.control { export function dmesg(s: string) { console.log("DMESG: " + s) } - } namespace pxsim.output { diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index e598839e..35b426c0 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -340,6 +340,28 @@ namespace pxsim.visuals { cancelAnimationFrame(animationId); }) } + // Save previous inputs for the next cycle + EV3View.previousSelectedInputs = ev3board().getInputNodes().map((node, index) => (this.getDisplayViewForNode(node.id, index).getSelected()) ? node.id : -1) + EV3View.previousSeletedOutputs = ev3board().getMotors().map((node, index) => (this.getDisplayViewForNode(node.id, index).getSelected()) ? node.id : -1); + } + + private static previousSelectedInputs: number[]; + private static previousSeletedOutputs: number[]; + + private static isPreviousInputSelected(index: number, id: number) { + if (EV3View.previousSelectedInputs && EV3View.previousSelectedInputs[index] == id) { + EV3View.previousSelectedInputs[index] = undefined; + return true; + } + return false; + } + + private static isPreviousOutputSelected(index: number, id: number) { + if (EV3View.previousSeletedOutputs && EV3View.previousSeletedOutputs[index] == id) { + EV3View.previousSeletedOutputs[index] = undefined; + return true; + } + return false; } private begin() { @@ -382,7 +404,9 @@ namespace pxsim.visuals { const view = this.getDisplayViewForNode(node.id, index); if (!node.didChange() && !view.didChange()) return; if (view) { - const control = view.getSelected() ? this.getControlForNode(node.id, index) : undefined; + const isSelected = EV3View.isPreviousInputSelected(index, node.id) || view.getSelected(); + if (isSelected && !view.getSelected()) view.setSelected(true); + const control = isSelected ? this.getControlForNode(node.id, index) : undefined; const closeIcon = control ? this.getCloseIconView() : undefined; this.layoutView.setInput(index, view, control, closeIcon); view.updateState(); @@ -401,7 +425,9 @@ namespace pxsim.visuals { const view = this.getDisplayViewForNode(node.id, index); if (!node.didChange() && !view.didChange()) return; if (view) { - const control = view.getSelected() ? this.getControlForNode(node.id, index) : undefined; + const isSelected = EV3View.isPreviousOutputSelected(index, node.id) || view.getSelected(); + if (isSelected && !view.getSelected()) view.setSelected(true); + const control = isSelected ? this.getControlForNode(node.id, index) : undefined; const closeIcon = control ? this.getCloseIconView() : undefined; this.layoutView.setOutput(index, view, control, closeIcon); view.updateState(); diff --git a/sim/visuals/nodes/colorSensorView.ts b/sim/visuals/nodes/colorSensorView.ts index 62d82023..5637af6d 100644 --- a/sim/visuals/nodes/colorSensorView.ts +++ b/sim/visuals/nodes/colorSensorView.ts @@ -14,6 +14,7 @@ namespace pxsim.visuals { } public updateState() { + super.updateState(); // TODO: show different color modes } } diff --git a/sim/visuals/nodes/largeMotorView.ts b/sim/visuals/nodes/largeMotorView.ts index 62ef88c9..0e10e685 100644 --- a/sim/visuals/nodes/largeMotorView.ts +++ b/sim/visuals/nodes/largeMotorView.ts @@ -10,6 +10,7 @@ namespace pxsim.visuals { } updateState() { + super.updateState(); const motorState = ev3board().getMotors()[this.port]; if (!motorState) return; const speed = motorState.getSpeed(); diff --git a/sim/visuals/nodes/mediumMotorView.ts b/sim/visuals/nodes/mediumMotorView.ts index b1f17f3f..d980f95e 100644 --- a/sim/visuals/nodes/mediumMotorView.ts +++ b/sim/visuals/nodes/mediumMotorView.ts @@ -20,6 +20,7 @@ namespace pxsim.visuals { } updateState() { + super.updateState(); const motorState = ev3board().getMotors()[this.port]; if (!motorState) return; const speed = motorState.getSpeed(); diff --git a/sim/visuals/nodes/moduleView.ts b/sim/visuals/nodes/moduleView.ts index 051f074d..ede63633 100644 --- a/sim/visuals/nodes/moduleView.ts +++ b/sim/visuals/nodes/moduleView.ts @@ -4,7 +4,8 @@ namespace pxsim.visuals { protected content: SVGSVGElement; protected controlShown: boolean; - protected selected: boolean; + + protected opacity: number; constructor(protected xml: string, protected prefix: string, protected id: NodeType, protected port: NodeType) { super(); @@ -106,19 +107,24 @@ namespace pxsim.visuals { this.updateOpacity(); } + public updateState() { + this.updateOpacity(); + } + protected updateOpacity() { if (this.rendered) { - const opacity = this.selected ? "0.2" : "1"; - if (this.hasClick()) { - this.setOpacity(opacity); + const opacity = this.selected ? 0.2 : 1; + if (this.hasClick() && this.opacity != opacity) { + this.opacity = opacity; + this.setOpacity(this.opacity); if (this.selected) this.content.style.cursor = ""; else this.content.style.cursor = "pointer"; } } } - protected setOpacity(opacity: string) { - this.element.setAttribute("opacity", opacity); + protected setOpacity(opacity: number) { + this.element.setAttribute("opacity", `${opacity}`); } } } \ No newline at end of file diff --git a/sim/visuals/view.ts b/sim/visuals/view.ts index 7e46300c..b0d7ae9f 100644 --- a/sim/visuals/view.ts +++ b/sim/visuals/view.ts @@ -219,7 +219,6 @@ namespace pxsim.visuals { this.changed = false; return res; } - } export abstract class SimView extends View implements LayoutElement { From 4dff282633046043db59a77ebe0a4761f69e21d1 Mon Sep 17 00:00:00 2001 From: Caitlin Hennessy Date: Thu, 21 Dec 2017 11:00:54 -0800 Subject: [PATCH 17/21] Initial work --- docs/static/fonts/icons/iconfont.css | 63 +++++++++++++++++++++++-- docs/static/fonts/icons/iconfont.eot | Bin 2504 -> 4892 bytes docs/static/fonts/icons/iconfont.svg | 57 ++++++++++++++++++++++ docs/static/fonts/icons/iconfont.ttf | Bin 2336 -> 4724 bytes docs/static/fonts/icons/iconfont.woff | Bin 1464 -> 2768 bytes docs/static/fonts/icons/iconfont.woff2 | Bin 1044 -> 2136 bytes libs/ev3/ns.ts | 6 +-- svgicons/generateIcons.js | 23 ++++++++- theme/blockly.less | 62 +++++++++++++++++++++++- 9 files changed, 202 insertions(+), 9 deletions(-) diff --git a/docs/static/fonts/icons/iconfont.css b/docs/static/fonts/icons/iconfont.css index f81b9f9f..67dd1f89 100644 --- a/docs/static/fonts/icons/iconfont.css +++ b/docs/static/fonts/icons/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; - src: url("iconfont.eot?e05611aaee246c1da118a83eaf515de9?#iefix") format("embedded-opentype"), -url("iconfont.woff2?e05611aaee246c1da118a83eaf515de9") format("woff2"), -url("iconfont.woff?e05611aaee246c1da118a83eaf515de9") format("woff"); + src: url("iconfont.eot?1aaa45a81be328d93991341b518bf26d?#iefix") format("embedded-opentype"), +url("iconfont.woff2?1aaa45a81be328d93991341b518bf26d") format("woff2"), +url("iconfont.woff?1aaa45a81be328d93991341b518bf26d") format("woff"); } .icon { @@ -28,3 +28,60 @@ url("iconfont.woff?e05611aaee246c1da118a83eaf515de9") format("woff"); .icon-gyro:before { content: "\f104"; } +.icon-addpackage:before { + content: "\f105"; +} +.icon-advancedcollapsed:before { + content: "\f106"; +} +.icon-advancedexpanded:before { + content: "\f107"; +} +.icon-brick:before { + content: "\f108"; +} +.icon-controls:before { + content: "\f109"; +} +.icon-functions:before { + content: "\f10a"; +} +.icon-list:before { + content: "\f10b"; +} +.icon-logic:before { + content: "\f10c"; +} +.icon-loops:before { + content: "\f10d"; +} +.icon-math:before { + content: "\f10e"; +} +.icon-motors:before { + content: "\f10f"; +} +.icon-music:before { + content: "\f110"; +} +.icon-sensors:before { + content: "\f111"; +} +.icon-text:before { + content: "\f112"; +} +.icon-variables:before { + content: "\f113"; +} +.icon-cancel:before { + content: "\f114"; +} +.icon-check:before { + content: "\f115"; +} +.icon-download:before { + content: "\f116"; +} +.icon-save:before { + content: "\f117"; +} diff --git a/docs/static/fonts/icons/iconfont.eot b/docs/static/fonts/icons/iconfont.eot index e4aa0b6d5d1024fa71e16aabdc3e6a76fa3b42da..007b931f7785852bff938eee072136a40040c8a7 100644 GIT binary patch literal 4892 zcmd^DO^jPt6+Y*_``+`<#P-bi`FWC=jN>=4L#E7(?XgWeWCFCLR76nq4~Yu3j_vtr zJ@#NbA*qTKp;kgrMcs8lg}SIB76_y)xq>4qC2)gJBRWvOip&G%CQoeKFGigJX z?6{tDf6hJc-t%|QxpNoiiN>t?b@I*+&=%}+qbdPUWWFm zO#|xFj;Y6(NYNwIrCqv6J!;Vqm>fL;%#cQ)7TN+;XpJ^7bGPq-mQ9m%l`PtL@X^P= zQuy)7=YaeIu#bK7(e>(MSO2OpehK3z+6S$}zrFXhZ$O#{0I%=%uI%i-^vs`#>_wu) z#$LD8$^B*hUC{mk(AWbaS$pFn^nVRl**h3twtjT;8rJ(G#!vSK?bgbTVv0zAh;j9x zb@`B2=>YS2j0^qNLH8%GyqO?MpT~Z=!@+1ge{Oz@Xto2IBZl`=pd?zodF_p#KlHr8 z7(`U%4F)p4{o?uUr_x{i2V^y0yz}%8@J%G`&1>&}{Lu5)Z($gV%!TDK%0sDfp)%M6 zffM?~jKlc^6uS*&oIC#*rFyM#pN$i@Iw+Ro^B2upcr1hnR9i;!i0O6G2 zK}7ceAQxYa_I?gn;o=^&kN|j1@E;>R@Du+N=ySqSgD%vF0C<|wU(m1V8~QE%o-GkbG$JQt2{PpA1bv`zrXnkG@XdqNj;!tGs!JgLIB*C9Zjamvzg<6odccTy30zQa0C=@73x7pc%D(u~ctDyhb&bbzDybthh_;pXEB_ zp9)(pD$7zu@TquCJBlr4?b;%Tp5xPe3Xru#E++=8g=xho=s_%Id%=;RvtTm^+Hoz0 zyxPcasaY2#8AHiw2(KO6cJP&@@IbI037;r}97rEHzgS}8lk73Xw%(0jf+BiP39F(|Jz#A;}FIPi&Sqn|`yBOS8Yt>s%{C40mdzU^WT$ za$JE)&KUiRy*Md50>Guro338gdfDP4aN?Ur4z%G={87k}if&%};Fq*Q0nSDSJmw{1 zHM7T+_!7gpn(#9LzE=hJ!n@s=Ynv*i#T#yZpXar!8K{`nF<4{%gX^#$BGdaH-~X!V zxe`ajU#Dx`{{y9FQYkQSYX;{DYzRGWOfMpPiw_7rROAE7fbADR6c;^Te>WcEIKrVs zLIT&P3_ZM~UUT6B#l^*ZmP<|=k;vp@q7w8Tu9-%>K_r=SA#FM03LX_WTF;ojV~NC! z`8%;FB^l4h%=JN{toUYNEcs=6O1!du7RN5x0-d5M@_-zC@xq6E5g2EQ#xUhj#9@h8@~)r-drd(CPB{NSsED$0nroY`wrocb z@L_BMw2L^GvXBO}9fRr+46GbPu`R?1$ROXTD03TLipYm2z)1<`dvjYMe3#%c-WJ35 zK{lmI<>qntObkL`)tHNzizW4(WlOSgT^wlFfwYo+urz4kBM3m2398^x+fmL7sAzKD zB4l5|j!sZ^%gr)e%y%V}){NbPx*W76oVX^;mVw^1h=)+EV-7nGFQlZz#37=;w4fa) zZ8?aW7L**G#}(|dgcE|DVDP%Trcx>^xv5!BsWk;z5#uDc79DR1MoK~+2kvIOaTkt` z7H$hoC!jEtqhMu5^baK>yg+&g3rk2RA;vbLBf6u?xh!Gl|#AxAGeGd3yFI2TUU(H)NV2mL~2ZDWdhu-oqrTjOr0aN$Z}bZNIb9`6)(hJ%B`Ijqy|^#+B* z;ozBWd%U(c9v|MfzAozveyu$?_^)S;&pv6~`RH-y`0mdgcTzowN0GjH7-`WMZ3n)5 zfv%t)(Iq^fRDm7iVWj{V;^E`~y>rnsOBatTJ@gCEx6D0*@7thWqdoK0A?{}D_)VW> zru1v(xdyKpQH(R@ziX8@*;MkigFB?$QxdqE%^(Y;IE}mHEYI;gXW8Q%`*6GkN?h!X zhpo||zu&gogWh0hj|UgqdwTcEaFA$qI)|&h0_+Gy^Xm#|cb*XE_|2GAe27&+p delta 516 zcmXv}JxfDD5Zt}H7o&*;RQvz~79s{yh=r&aO=n>x1Pc-Mk*F#1OoAz*h_SQ~A$f}U zQTPJ{3%eju)4~S?!>Dalg?azDEU%=UVW^3*AB{oMSFM;0ls+|g21Fh(N1xC{lXr6|V-va$< zr%|&0)$-#X$>b?!zDXpHL+_ez-U?4hk+08=i>ex@@ ze@4SBF?bLl!jeBf6g7$w{>U;4`mSq@>T+oElLFpEeeq*O_ju9FMo{`mXcb3$Tka$0 zIqZ&!>5?*Yk|O_(rc0CF0PmaFr3JD82}A(}tA)S45>T~o6cN9I?zt*N=|qu{GD{&eNueMxj=1>< Sjf;SVO0r@L#!GEsz3wlhepC1W diff --git a/docs/static/fonts/icons/iconfont.svg b/docs/static/fonts/icons/iconfont.svg index 36778eab..b3a250b6 100644 --- a/docs/static/fonts/icons/iconfont.svg +++ b/docs/static/fonts/icons/iconfont.svg @@ -19,6 +19,63 @@ + + + + + + + + + + + + + + + + + + + diff --git a/docs/static/fonts/icons/iconfont.ttf b/docs/static/fonts/icons/iconfont.ttf index 1eb7bf3d514fc8fcd5e86233366c75377ee775be..115c9d92b699b0c1db4b952821968fa7fe866e11 100644 GIT binary patch literal 4724 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 fV!tT&x@&xrpYBR%y# delta 446 zcmXX=%}N4c6uozTVo*bf2m>nvi9{FCBBHX|wTKphxQL*J(VSq$F&#l$WDgJ_P7&3{ z2MAiYi>Tfqk!aPT7YLNv*_qJ~&iy&}ocrBwv^iFf)K<>6;zWEwL}|@b3)R!!8~Q)s zE@xDaZasd7ukmp9B{Q{PB5R|3`)XzXvH|+{FP!WG4j2o7wazn_#dxbt= zs+9tV$izH^K9X0>TK4|t#YZ%P1;RwZD%r`0YlTQ@L$FPZI1dov$bO#^9^(`e0sPdRno@JpUgq!_XD$up~%LLmYP zK!Ra!_rNo!cJKqQgbe;ia?XXx)~n!WA8kVCKFMi|ivh1pQHR(0vK5v^QDAmv rl~8LZxGcnF7FcA7Wga14*|3Xh$;uyVvSt}pQMRqJrc1eM(ZZI0rjt@t diff --git a/docs/static/fonts/icons/iconfont.woff b/docs/static/fonts/icons/iconfont.woff index ab8f84de0c9eb6a665f31464f16bb16801e5de56..e8d97e861622f65d6bef57152c6c45535850b2ad 100644 GIT binary patch delta 2351 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 KqHw3d0001CZUj33 delta 1031 zcmV+i1o->d5R?cQcTYw#00961000CO01E&B000Rf000BXkr*9+gBl8k9ECvvHUcCA z6blRh1Rw>376(fk^9K=?oWIDv7_gg*Ss5FdnWWK{2jBFVTAH^;J5TB9%;z#@~P+h!9TP}Z}-4tzUZ(63c&x;I1O&El2y^1pg&WMgy8reK^Kfufkf-a_^QZU8pITf`rpOUl%dv&}1rN++0pRt= zOGE&Jx9}EMo}7Hdkq>=vtN|=**W!WW2Q9GSJbK-04cx$gq6f+ncyo6-9D)z-|34_v zqqF|QGgurbgQ-&h96`{*2SpN8W*`AF3ki@p@IQn@17qk|%5z1FM6Fglyxap~` zHP0!XhOqiNj%kRIm7MJRVFY-;YN9Ve?&0{C)etmBHi~!axd& z8Ypu62qJ-hezobl;c!$}qX8OeRhIbH5)~r(ZuPJIZmf1W@%Il+g`cAe>bBJ(1dAhf zhX&H9iLtLQB7<{Pts2!twQI4kM1f%ySdDhzDZKv9H&BpfWg!MJ))lQWGzZqk7*DH( zs1{YBu5RvXn?Z|H8dX(2nKVsokgBsx2!G9_(icmA(~{&eWlDDGa<_b`-&*<;>rApe zYf9%#afvIp`lZYLiG6DLELJZwlDBhhCYfbInVD<6DBSfrTZY}f-GTSqD`5J*y0*Pprxuve>3W|jZxm24BnW&DU5t*rz6X^it zoxEp%{Lt-miK%3X8*Fn{vLpE0}sl1J8P!Qbc4Zz`M@%o&X4 zjnT8dXGk06ephZUSLN-T`+4`r01OBM_}|!nlizie`p>3<(UIq3`BngIU%;;0CYeK zfsIann|I1wt9O#R<=B&==x{JT$R)B7fUUF{#r)1nUgqNo;>{G8wJg(wHQ3BEtI7rt zg!Xw}2~OA@TlBwd1ZuGOz#mJC;9>_q(0+S*q(V3wpys` B=Ai%p diff --git a/libs/ev3/ns.ts b/libs/ev3/ns.ts index 31a7b1f0..8db92e47 100644 --- a/libs/ev3/ns.ts +++ b/libs/ev3/ns.ts @@ -1,19 +1,19 @@ -//% color="#68C3E2" weight=100 +//% color="#68C3E2" weight=100 icon="\uf108" //% groups='["Buttons", "Screen"]' //% labelLineWidth=0 namespace brick { } -//% color="#C8509B" weight=95 icon="\uf192" +//% color="#C8509B" weight=95 icon="\uf111" //% labelLineWidth=0 //% groups='["Ultrasonic Sensor", "Touch Sensor", "Color Sensor", "Infrared Sensor", "Remote Infrared Beacon", "Gyro Sensor"]' //% groupIcons='["\uf101","\uf103","\uf102","","","\uf104"]' namespace sensors { } -//% color="#A5CA18" weight=90 icon="\uf185" +//% color="#A5CA18" weight=90 icon="\uf10f" //% groups='["Motion", "Sensors", "Chassis"]' //% labelLineWidth=0 namespace motors { diff --git a/svgicons/generateIcons.js b/svgicons/generateIcons.js index 30863fa8..3b316ecf 100644 --- a/svgicons/generateIcons.js +++ b/svgicons/generateIcons.js @@ -2,10 +2,29 @@ const webfontsGenerator = require('webfonts-generator'); webfontsGenerator({ files: [ - './ultrasonic.svg', + "./ultrasonic.svg", "./color.svg", "./touch.svg", - "./gyro.svg" + "./gyro.svg", + "./categories/addpackage.svg", + "./categories/advancedcollapsed.svg", + "./categories/advancedexpanded.svg", + "./categories/brick.svg", + "./categories/controls.svg", + "./categories/functions.svg", + "./categories/list.svg", + "./categories/logic.svg", + "./categories/loops.svg", + "./categories/math.svg", + "./categories/motors.svg", + "./categories/music.svg", + "./categories/sensors.svg", + "./categories/text.svg", + "./categories/variables.svg", + "./icons/cancel.svg", + "./icons/check.svg", + "./icons/download.svg", + "./icons/save.svg" ], dest: '../docs/static/fonts/icons/', round: 10 diff --git a/theme/blockly.less b/theme/blockly.less index 4d980269..341a2c52 100644 --- a/theme/blockly.less +++ b/theme/blockly.less @@ -9,7 +9,7 @@ /* Fonts for toolbox icons */ @font-face { font-family: 'legoIcons'; - src: data-uri("../docs/static/fonts/icons/iconfont.woff2"); + src: data-uri("../docs/static/fonts/icons/iconfont.woff") format('woff'); } .blocklyFlyoutLabel:not(.blocklyFlyoutHeading) .blocklyFlyoutLabelIcon { @@ -18,6 +18,10 @@ font-size: 1.7rem; } +span.blocklyTreeIcon { + font-family: 'legoIcons' !important; +} + /* Toolbox padding */ .blocklyToolboxDiv, .monacoToolboxDiv { padding: 0.5rem; @@ -67,4 +71,60 @@ span.blocklyTreeLabel { #blocklyTrashIcon { margin: 0.2rem; } +} + +span.blocklyTreeIcon.blocklyTreeIcontests::before { + content: ""; +} + +span.blocklyTreeIcon.blocklyTreeIconmusic::before { + content: "\f110"; +} + +span.blocklyTreeIcon.blocklyTreeIconloops::before { + content: "\f10d"; +} + +span.blocklyTreeIcon.blocklyTreeIconlogic::before { + content: "\f10c"; +} + +span.blocklyTreeIcon.blocklyTreeIconvariables::before { + content: "\f113"; +} + +span.blocklyTreeIcon.blocklyTreeIconmath::before { + content: "\f10e"; +} + +span.blocklyTreeIcon.blocklyTreeIconadvancedcollapsed::before { + content: "\f106"; +} + +span.blocklyTreeIcon.blocklyTreeIconadvancedexpanded::before { + content: "\f107"; +} + +span.blocklyTreeIcon.blocklyTreeIconfunctions::before { + content: "\f10a"; +} + +span.blocklyTreeIcon.blocklyTreeIconarrays::before { + content: ""; +} + +span.blocklyTreeIcon.blocklyTreeIcontext::before { + content: "\f112"; +} + +span.blocklyTreeIcon.blocklyTreeIconconsole::before { + content: ""; +} + +span.blocklyTreeIcon.blocklyTreeIconcontrol::before { + content: "\f109"; +} + +span.blocklyTreeIcon.blocklyTreeIconaddpackage::before { + content: "\f105"; } \ No newline at end of file From 7affbf8cb65977809c738098cc47f4b20137b9bf Mon Sep 17 00:00:00 2001 From: Caitlin Hennessy Date: Thu, 21 Dec 2017 11:10:47 -0800 Subject: [PATCH 18/21] Save, download --- theme/blockly.less | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/theme/blockly.less b/theme/blockly.less index 341a2c52..2854fb60 100644 --- a/theme/blockly.less +++ b/theme/blockly.less @@ -110,7 +110,7 @@ span.blocklyTreeIcon.blocklyTreeIconfunctions::before { } span.blocklyTreeIcon.blocklyTreeIconarrays::before { - content: ""; + content: "\f10b"; } span.blocklyTreeIcon.blocklyTreeIcontext::before { @@ -127,4 +127,13 @@ span.blocklyTreeIcon.blocklyTreeIconcontrol::before { span.blocklyTreeIcon.blocklyTreeIconaddpackage::before { content: "\f105"; -} \ No newline at end of file +} + +.save-editortools-btn .icon.save::before { + content: "\f117" +} + +.download-button .icon.download.icon-and-text::before { + content: "\f116" +} + From e240e3b394321ecc76fff80b15f64145c167ec7c Mon Sep 17 00:00:00 2001 From: Caitlin Hennessy Date: Thu, 21 Dec 2017 11:30:32 -0800 Subject: [PATCH 19/21] Check, cancel --- theme/blockly.less | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/theme/blockly.less b/theme/blockly.less index 2854fb60..4a15ab27 100644 --- a/theme/blockly.less +++ b/theme/blockly.less @@ -9,7 +9,7 @@ /* Fonts for toolbox icons */ @font-face { font-family: 'legoIcons'; - src: data-uri("../docs/static/fonts/icons/iconfont.woff") format('woff'); + src: data-uri("../docs/static/fonts/icons/iconfont.woff2"); } .blocklyFlyoutLabel:not(.blocklyFlyoutHeading) .blocklyFlyoutLabelIcon { @@ -137,3 +137,11 @@ span.blocklyTreeIcon.blocklyTreeIconaddpackage::before { content: "\f116" } +.button.approve.positive .checkmark.icon::before { + content: "\f115" +} + +.button.approve.cancel .cancel.icon::before { + content: "\f114" +} + From 383ca5467d2845247673f5420e3c5550fe0ae0fd Mon Sep 17 00:00:00 2001 From: Caitlin Hennessy Date: Tue, 2 Jan 2018 12:49:25 -0800 Subject: [PATCH 20/21] Remove advexpanded/advcollapsed --- docs/static/fonts/icons/iconfont.css | 44 ++++++------ docs/static/fonts/icons/iconfont.eot | Bin 4892 -> 4716 bytes docs/static/fonts/icons/iconfont.svg | 38 +++++------ docs/static/fonts/icons/iconfont.ttf | Bin 4724 -> 4548 bytes docs/static/fonts/icons/iconfont.woff | Bin 2768 -> 2672 bytes docs/static/fonts/icons/iconfont.woff2 | Bin 2136 -> 2052 bytes libs/ev3/ns.ts | 6 +- svgicons/categories/advancedcollapsed.svg | 23 ------- svgicons/categories/advancedexpanded.svg | 23 ------- svgicons/generateIcons.js | 2 - theme/blockly.less | 78 +++++++++------------- 11 files changed, 69 insertions(+), 145 deletions(-) delete mode 100644 svgicons/categories/advancedcollapsed.svg delete mode 100644 svgicons/categories/advancedexpanded.svg diff --git a/docs/static/fonts/icons/iconfont.css b/docs/static/fonts/icons/iconfont.css index 67dd1f89..9f7a0a7b 100644 --- a/docs/static/fonts/icons/iconfont.css +++ b/docs/static/fonts/icons/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; - src: url("iconfont.eot?1aaa45a81be328d93991341b518bf26d?#iefix") format("embedded-opentype"), -url("iconfont.woff2?1aaa45a81be328d93991341b518bf26d") format("woff2"), -url("iconfont.woff?1aaa45a81be328d93991341b518bf26d") format("woff"); + src: url("iconfont.eot?d6ed5932401120dae3c35f6048fd5e76?#iefix") format("embedded-opentype"), +url("iconfont.woff2?d6ed5932401120dae3c35f6048fd5e76") format("woff2"), +url("iconfont.woff?d6ed5932401120dae3c35f6048fd5e76") format("woff"); } .icon { @@ -31,57 +31,51 @@ url("iconfont.woff?1aaa45a81be328d93991341b518bf26d") format("woff"); .icon-addpackage:before { content: "\f105"; } -.icon-advancedcollapsed:before { +.icon-brick:before { content: "\f106"; } -.icon-advancedexpanded:before { +.icon-controls:before { content: "\f107"; } -.icon-brick:before { +.icon-functions:before { content: "\f108"; } -.icon-controls:before { +.icon-list:before { content: "\f109"; } -.icon-functions:before { +.icon-logic:before { content: "\f10a"; } -.icon-list:before { +.icon-loops:before { content: "\f10b"; } -.icon-logic:before { +.icon-math:before { content: "\f10c"; } -.icon-loops:before { +.icon-motors:before { content: "\f10d"; } -.icon-math:before { +.icon-music:before { content: "\f10e"; } -.icon-motors:before { +.icon-sensors:before { content: "\f10f"; } -.icon-music:before { +.icon-text:before { content: "\f110"; } -.icon-sensors:before { +.icon-variables:before { content: "\f111"; } -.icon-text:before { +.icon-cancel:before { content: "\f112"; } -.icon-variables:before { +.icon-check:before { content: "\f113"; } -.icon-cancel:before { +.icon-download:before { content: "\f114"; } -.icon-check:before { +.icon-save:before { content: "\f115"; } -.icon-download:before { - content: "\f116"; -} -.icon-save:before { - content: "\f117"; -} diff --git a/docs/static/fonts/icons/iconfont.eot b/docs/static/fonts/icons/iconfont.eot index 007b931f7785852bff938eee072136a40040c8a7..1de913218a6e6d5b05a4b2300f5cff06a3d07251 100644 GIT binary patch delta 419 zcmbQE_C|#*M~H#ph~PvvGnR){3QZFoI_iVYEjq%$z}UmUzz~+4n^^GacylWQ1CtF9 zcckZ3rUgvyYh++x`NF`!c_AY;F-4rG8^~sO0K{e)Kml&!ZSR2WJwU9Iky}#1Y;~{? zXxNE8S_`otz5W8BCs3f93Ky+R^zauZYXQW-vIt~`D;QTwR?ng?(rZyV09&GGAi7-N>EiVtp2&ENS3`1*j}a|O#V6I*9D z*!!6oF0c^HyxHdcJ0@MQD^>YqrNQ6(!u4daoHx>~6JbDo<@&sBR2@14oBKM~{UyUb zZoPQ+p%;kc_=gFnJY9)jjgJ6PlTC+QlTw#;5Sy9RdM~I-?@Kg?OPIo`i>tM1wA)B3J(w!A~_q_w170$nI{4GoOZPP~d0a zReAbO((RWcJqaYa=YM5Lig7c - - diff --git a/docs/static/fonts/icons/iconfont.ttf b/docs/static/fonts/icons/iconfont.ttf index 115c9d92b699b0c1db4b952821968fa7fe866e11..268395b897f68b6f0f122b81bd5f8b104a54d96a 100644 GIT binary patch delta 389 zcmeyOazuH8LVeJ=MMoGI7<(8P7{Zcs6AL~aZ*FB^V6p+?j`W<$w1CNdjSLJdUlYpD8OyJ?H!Q42Z&WNa!V?htq%49&3gjmN95!uCn|c#0p(bL zb};DWCRP+MYBJ;kY;@i21ofJ_Af(aBes|LFi3Aq>|T?HKzQcQKw}{K8bibdFhs*^9Y}`2h1T78jNf omI9V0mMJWoSYB+FVl8Lh{E=e{2cy{JHbI@q+XOWxGYS;}03!=vwEzGB delta 576 zcmXw#PiPZC6vn?dGqsy0O&W{IDk{ZYu-1ZNP!H93XpsuVgA|Y2CA%g_HVHOpEP_GW ziTFU0{-^woD{s#0M2Kr9tJjYFJo@z1snRPD5MmY6mi{~pW zJLi`x@^Q1q`+ebhCSS}rcH>wSP+z$|<2#iSorKTpCf7p+$3Nn|c>b;rh)wZ#)E}0-^Ssxar(l=ulej$uucCa?n;G6x+&DzH9l?U}Umj*=Oas+** zK1#2{$!>?Nw+~6(qKxhrhQ28FpQv^jU=Ff78|BQGp(+&k7kE^Gzn#<-G1i+vlGpa> zrueNtif}B_J;V-1j--AsJCoZ9##sn5nrifxKGApjBW$rGI&wnJ$%fog zBdVM1>%JHuFGw zf&XETx6Y=LtmCZoJVT*Sh^XEQ85E-BtnthsQ+EbN6`6EUkHm+qxZ~b+3K`GM6!Uqf VH0!wodyZErIR)2q^|kmN!e7LlgJu8# diff --git a/docs/static/fonts/icons/iconfont.woff b/docs/static/fonts/icons/iconfont.woff index e8d97e861622f65d6bef57152c6c45535850b2ad..a61fb1dcc0e821422d5a41b0a42748434893a57c 100644 GIT binary patch delta 2223 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 I2WD7BbfyJ1a{vGU diff --git a/docs/static/fonts/icons/iconfont.woff2 b/docs/static/fonts/icons/iconfont.woff2 index 8d9eab3da4bb0eb610b9cc8a5984d86aace46eb7..91b8d812b98cfa2ef6847e2eecb3fda2ae2d6a18 100644 GIT binary patch delta 2046 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 - - - -color - - - - - - - - - - - - - - - diff --git a/svgicons/categories/advancedexpanded.svg b/svgicons/categories/advancedexpanded.svg deleted file mode 100644 index f4b42b1b..00000000 --- a/svgicons/categories/advancedexpanded.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - -color - - - - - - - - - - - - - - - diff --git a/svgicons/generateIcons.js b/svgicons/generateIcons.js index 3b316ecf..01b276cc 100644 --- a/svgicons/generateIcons.js +++ b/svgicons/generateIcons.js @@ -7,8 +7,6 @@ webfontsGenerator({ "./touch.svg", "./gyro.svg", "./categories/addpackage.svg", - "./categories/advancedcollapsed.svg", - "./categories/advancedexpanded.svg", "./categories/brick.svg", "./categories/controls.svg", "./categories/functions.svg", diff --git a/theme/blockly.less b/theme/blockly.less index 4a15ab27..efc223c2 100644 --- a/theme/blockly.less +++ b/theme/blockly.less @@ -73,56 +73,40 @@ span.blocklyTreeLabel { } } -span.blocklyTreeIcon.blocklyTreeIcontests::before { - content: ""; -} - span.blocklyTreeIcon.blocklyTreeIconmusic::before { - content: "\f110"; -} - -span.blocklyTreeIcon.blocklyTreeIconloops::before { - content: "\f10d"; -} - -span.blocklyTreeIcon.blocklyTreeIconlogic::before { - content: "\f10c"; -} - -span.blocklyTreeIcon.blocklyTreeIconvariables::before { - content: "\f113"; -} - -span.blocklyTreeIcon.blocklyTreeIconmath::before { content: "\f10e"; } -span.blocklyTreeIcon.blocklyTreeIconadvancedcollapsed::before { - content: "\f106"; -} - -span.blocklyTreeIcon.blocklyTreeIconadvancedexpanded::before { - content: "\f107"; -} - -span.blocklyTreeIcon.blocklyTreeIconfunctions::before { - content: "\f10a"; -} - -span.blocklyTreeIcon.blocklyTreeIconarrays::before { +span.blocklyTreeIcon.blocklyTreeIconloops::before { content: "\f10b"; } -span.blocklyTreeIcon.blocklyTreeIcontext::before { - content: "\f112"; +span.blocklyTreeIcon.blocklyTreeIconlogic::before { + content: "\f10a"; } -span.blocklyTreeIcon.blocklyTreeIconconsole::before { - content: ""; +span.blocklyTreeIcon.blocklyTreeIconvariables::before { + content: "\f111"; +} + +span.blocklyTreeIcon.blocklyTreeIconmath::before { + content: "\f10c"; +} + +span.blocklyTreeIcon.blocklyTreeIconfunctions::before { + content: "\f108"; +} + +span.blocklyTreeIcon.blocklyTreeIconarrays::before { + content: "\f109"; +} + +span.blocklyTreeIcon.blocklyTreeIcontext::before { + content: "\f110"; } span.blocklyTreeIcon.blocklyTreeIconcontrol::before { - content: "\f109"; + content: "\f107"; } span.blocklyTreeIcon.blocklyTreeIconaddpackage::before { @@ -130,18 +114,18 @@ span.blocklyTreeIcon.blocklyTreeIconaddpackage::before { } .save-editortools-btn .icon.save::before { - content: "\f117" -} - -.download-button .icon.download.icon-and-text::before { - content: "\f116" -} - -.button.approve.positive .checkmark.icon::before { content: "\f115" } -.button.approve.cancel .cancel.icon::before { +.download-button .icon.download.icon-and-text::before { content: "\f114" } +.button.approve.positive .checkmark.icon::before { + content: "\f113" +} + +.button.approve.cancel .cancel.icon::before { + content: "\f112" +} + From a7c62b45b2f17e3019611caa2c1366d897663b2f Mon Sep 17 00:00:00 2001 From: Caitlin Hennessy Date: Tue, 2 Jan 2018 13:01:28 -0800 Subject: [PATCH 21/21] Use legoIcons font for flyout headings --- theme/blockly.less | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/theme/blockly.less b/theme/blockly.less index efc223c2..4bd7b422 100644 --- a/theme/blockly.less +++ b/theme/blockly.less @@ -13,11 +13,14 @@ } .blocklyFlyoutLabel:not(.blocklyFlyoutHeading) .blocklyFlyoutLabelIcon { - font-family: 'legoIcons'; fill: white; font-size: 1.7rem; } +.blocklyFlyoutLabel .blocklyFlyoutLabelIcon { + font-family: 'legoIcons'; +} + span.blocklyTreeIcon { font-family: 'legoIcons' !important; }