diff --git a/libs/blocksprj/main.blocks b/libs/blocksprj/main.blocks index b223d66e..415a3503 100644 --- a/libs/blocksprj/main.blocks +++ b/libs/blocksprj/main.blocks @@ -1,3 +1,5 @@ - + + + \ No newline at end of file diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index d3be5c8a..3f6f72aa 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -298,7 +298,14 @@ namespace pxsim.visuals { this.layoutView.inject(this.element); // Add EV3 module element - this.layoutView.setBrick(new BrickView(-1)); + const brickCloseIcon = this.getCloseIconView(); + brickCloseIcon.registerClick(ev => { + this.layoutView.unselectBrick(); + this.resize(); + }); + const brick =new BrickView(-1); + brick.setSelected(EV3View.isPreviousBrickSelected()); + this.layoutView.setBrick(brick, brickCloseIcon); this.resize(); @@ -329,6 +336,12 @@ namespace pxsim.visuals { this.screenCanvas = document.createElement("canvas"); this.screenCanvas.id = "board-screen-canvas"; this.screenCanvas.style.position = "absolute"; + this.screenCanvas.addEventListener(pxsim.pointerEvents.up, ev => { + this.layoutView.selectBrick(); + this.resize(); + }) + this.screenCanvas.style.cursor = "pointer"; + /* this.screenCanvas.style.cursor = "crosshair"; this.screenCanvas.onmousemove = (e: MouseEvent) => { const x = e.clientX; @@ -340,6 +353,7 @@ namespace pxsim.visuals { this.screenCanvas.onmouseleave = () => { this.updateXY(SCREEN_WIDTH, SCREEN_HEIGHT); } + */ this.screenCanvas.width = SCREEN_WIDTH; this.screenCanvas.height = SCREEN_HEIGHT; @@ -360,10 +374,12 @@ namespace pxsim.visuals { // 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); + EV3View.previousSelectedBrick = this.layoutView.getBrick().getSelected(); } private static previousSelectedInputs: number[]; private static previousSeletedOutputs: number[]; + private static previousSelectedBrick: boolean; private static isPreviousInputSelected(index: number, id: number) { if (EV3View.previousSelectedInputs && EV3View.previousSelectedInputs[index] == id) { @@ -381,6 +397,12 @@ namespace pxsim.visuals { return false; } + private static isPreviousBrickSelected() { + const b = EV3View.previousSelectedBrick; + EV3View.previousSelectedBrick = false; + return !!b; + } + private begin() { this.running = true; this.updateState(); diff --git a/sim/visuals/layoutView.ts b/sim/visuals/layoutView.ts index 78dea359..c62342f4 100644 --- a/sim/visuals/layoutView.ts +++ b/sim/visuals/layoutView.ts @@ -37,6 +37,8 @@ namespace pxsim.visuals { private outputWires: WireView[] = []; private brick: BrickView; + private brickCloseIcon: View = undefined; + private offsets: number[]; private contentGroup: SVGGElement; private scrollGroup: SVGGElement; @@ -67,16 +69,32 @@ namespace pxsim.visuals { this.position(); } - public setBrick(brick: BrickView) { + public setBrick(brick: BrickView, brickCloseIcon: View) { this.brick = brick; this.brick.inject(this.scrollGroup); - this.position(); + + this.brickCloseIcon = brickCloseIcon; + this.addView(this.brickCloseIcon); + this.brickCloseIcon.setVisible(this.brick.getSelected()); + this.position(); } public getBrick() { return this.brick; } + public unselectBrick() { + this.brick.setSelected(false); + this.brickCloseIcon.setVisible(false); + this.position(); + } + + public selectBrick() { + this.brick.setSelected(true); + this.brickCloseIcon.setVisible(true); + this.position(); + } + public setInput(port: number, view: LayoutElement, control?: View, closeIcon?: View) { if (this.inputs[port] != view || this.inputControls[port] != control) { if (this.inputs[port]) { @@ -224,17 +242,23 @@ namespace pxsim.visuals { 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); + // render the full brick layout, even when there are not connection + // otherwise, it creates flickering of the simulator. + if (this.brick.getSelected()) { + // render output button + const closeIconWidth = this.brickCloseIcon.getWidth(); + const closeIconHeight = this.brickCloseIcon.getHeight(); + this.brickCloseIcon.translate(contentWidth / 2 - closeIconWidth / 2, 0); + + // render the entire board + this.brick.resize(contentWidth, contentHeight - closeIconHeight * 2); + this.brick.translate(0, closeIconHeight * 2); // 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)); } + this.outputs.concat(this.inputs).forEach(m => m.setVisible(true)); const moduleHeight = this.getModuleHeight(); diff --git a/sim/visuals/view.ts b/sim/visuals/view.ts index b0d7ae9f..cbe95623 100644 --- a/sim/visuals/view.ts +++ b/sim/visuals/view.ts @@ -206,8 +206,10 @@ namespace pxsim.visuals { } public setSelected(selected: boolean) { - this.selected = selected; - this.setChangedState(); + if (this.selected != selected) { + this.selected = selected; + this.setChangedState(); + } } protected setChangedState() {