From 8215e8446ade6460f7ce01843c18d3d95b5692ff Mon Sep 17 00:00:00 2001 From: Sam El-Husseini Date: Wed, 12 Jul 2017 10:25:17 +0300 Subject: [PATCH] Sim screen canvas implementation and _setPixel. --- sim/dalboard.ts | 2 + sim/state/light.ts | 2 +- sim/state/screen.ts | 34 +++++++++++++++++ sim/visuals/board.svg | 54 +++++++++++++++++--------- sim/visuals/board.ts | 85 ++++++++++++++++++++++++++++++++++++++++- sim/visuals/boardsvg.ts | 58 +++++++++++++++++++--------- 6 files changed, 197 insertions(+), 38 deletions(-) create mode 100644 sim/state/screen.ts diff --git a/sim/dalboard.ts b/sim/dalboard.ts index 726d002b..3fd53b3d 100644 --- a/sim/dalboard.ts +++ b/sim/dalboard.ts @@ -48,6 +48,7 @@ namespace pxsim { touchButtonState: TouchButtonState; irState: InfraredState; lightState: EV3LightState; + screenState: EV3ScreenState; view: SVGSVGElement; @@ -60,6 +61,7 @@ namespace pxsim { this.builtinParts["buttons"] = this.buttonState = new EV3ButtonState(); this.builtinParts["light"] = this.lightState = new EV3LightState(); + this.builtinParts["screen"] = this.screenState = new EV3ScreenState(); /*this.builtinParts["neopixel"] = this.neopixelState = new CommonNeoPixelState(); this.builtinParts["buttonpair"] = this.buttonState = new CommonButtonState(); diff --git a/sim/state/light.ts b/sim/state/light.ts index 7ac7f1ed..c46db57b 100644 --- a/sim/state/light.ts +++ b/sim/state/light.ts @@ -11,7 +11,7 @@ namespace pxsim { namespace pxsim.output { - export function setLights(pattern: number){ + export function setLights(pattern: number) { const lightState = (board() as DalBoard).lightState; lightState.lightPattern = pattern; runtime.queueDisplayUpdate(); diff --git a/sim/state/screen.ts b/sim/state/screen.ts new file mode 100644 index 00000000..929fd62d --- /dev/null +++ b/sim/state/screen.ts @@ -0,0 +1,34 @@ + +namespace pxsim { + + export class EV3ScreenState { + points: {[x: number]: {[y: number]: number}}; + constructor() { + this.points = {}; + } + + setPixel(x: number, y: number, v: number) { + if (x < 0 || x > 178) return; + if (y < 0 || y > 128) return; + + const xPoints = this.points[x] + if (!xPoints) this.points[x] = {}; + this.points[x][y] = v; + } + } +} + + +namespace pxsim.screen { + + export function _setPixel(x: number, y: number, mode: Draw) { + const screenState = (board() as DalBoard).screenState; + screenState.setPixel(x, y, mode); + runtime.queueDisplayUpdate(); + } + + + export function _blitLine(xw: number, y: number, buf: number, mode: Draw) { + + } +} \ No newline at end of file diff --git a/sim/visuals/board.svg b/sim/visuals/board.svg index 50f13414..5c777f03 100644 --- a/sim/visuals/board.svg +++ b/sim/visuals/board.svg @@ -10,15 +10,22 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="169.82979" - height="259.11862" - viewBox="0 0 169.82979 259.11862" + width="99.984344" + height="151.66585" + viewBox="0 0 99.984346 151.66585" id="svg2" version="1.1" inkscape:version="0.91 r13725" sodipodi:docname="board.svg"> + @@ -696,7 +703,7 @@ inkscape:label="Button" inkscape:menu="Bevels" inkscape:menu-tooltip="Soft bevel, slightly depressed middle" - style="color-interpolation-filters:sRGB;" + style="color-interpolation-filters:sRGB" id="filter7573"> image/svg+xml - + @@ -933,10 +940,10 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" - transform="translate(-286.75886,-393.46077)"> + transform="translate(-321.68157,-447.18716)"> + transform="matrix(0.16751195,0,0,0.16751196,310.76765,431.68528)"> + id="Screen"> + ry="5" + id="rect196" /> + x, y diff --git a/sim/visuals/board.ts b/sim/visuals/board.ts index f2e8b545..235105ef 100644 --- a/sim/visuals/board.ts +++ b/sim/visuals/board.ts @@ -173,8 +173,10 @@ namespace pxsim.visuals { { 'name': "PWR_1", 'touch': 0, 'text': null, tooltip: "+3.3V" }, { 'name': "PWR_2", 'touch': 0, 'text': null, tooltip: "+3.3V" } ]; - const MB_WIDTH = 169.82979; - const MB_HEIGHT = 259.11862; + const MB_WIDTH = 99.984346; + const MB_HEIGHT = 151.66585; + const SCREEN_WIDTH = 178; + const SCREEN_HEIGHT = 128; export interface IBoardTheme { accent?: string; display?: string; @@ -240,6 +242,10 @@ namespace pxsim.visuals { private buttons: SVGElement[]; private buttonABText: SVGTextElement; private light: SVGElement; + private screenCanvas: HTMLCanvasElement; + private screenCanvasCtx: CanvasRenderingContext2D; + private screenCanvasData: ImageData; + private screenXYText: SVGTextElement; private pins: SVGElement[]; private pinControls: { [index: number]: AnalogPinControl }; private systemLed: SVGCircleElement; @@ -345,6 +351,7 @@ namespace pxsim.visuals { }) this.updateLight(); + this.updateScreen(); /* this.updatePins(); @@ -448,6 +455,34 @@ namespace pxsim.visuals { } } + private updateScreen() { + let state = this.board; + if (!state || !state.screenState) return; + + this.screenCanvasData = this.screenCanvasCtx.getImageData(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + + Object.keys(state.screenState.points).forEach(xStr => { + const x = parseInt(xStr); + Object.keys(state.screenState.points[x]).forEach(yStr => { + const y = parseInt(yStr); + + const point = state.screenState.points[x][y]; + const r = 0; + const g = 0; + const b = 0; + const a = 255; + + var index = (x + y * SCREEN_WIDTH) * 4; + this.screenCanvasData.data[index + 0] = r; + this.screenCanvasData.data[index + 1] = g; + this.screenCanvasData.data[index + 2] = b; + this.screenCanvasData.data[index + 3] = a; + }) + }) + + this.screenCanvasCtx.putImageData(this.screenCanvasData, 0, 0); + } + private updateNeoPixels() { let state = this.board; if (!state || !state.neopixelState) return; @@ -700,6 +735,12 @@ namespace pxsim.visuals { this.element.style.perspective = "30em"; } + private updateXY() { + this.screenXYText.textContent = `x:${this.currentCanvasX}, y:${this.currentCanvasY}`; + } + + private currentCanvasX = 178; + private currentCanvasY = 128; private buildDom() { this.element = new DOMParser().parseFromString(BOARD_SVG, "image/svg+xml").querySelector("svg") as SVGSVGElement; svg.hydrate(this.element, { @@ -723,6 +764,46 @@ namespace pxsim.visuals { this.buttons.forEach(b => svg.addClass(b, "sim-button")); this.light = this.element.getElementById("BOARD_Light") as SVGElement; + + const screen = this.element.getElementById("Screen"); + const foreignObjectG = svg.child(screen, "g", { + transform: "scale(1.75)" + }) + const foreignObject = svg.child(foreignObjectG, "foreignObject", { + x: "119", y: "105", width: "178", height: "128" + }); + + const foBody = document.createElementNS("http://www.w3.org/1999/xhtml", "body") as HTMLElement; + foBody.style.width = `${SCREEN_WIDTH}px`; + foBody.style.height = `${SCREEN_HEIGHT}px`; + foBody.style.position = 'fixed'; + foBody.style.backgroundColor = `none`; + foreignObject.appendChild(foBody); + + this.screenCanvas = document.createElement("canvas"); + this.screenCanvas.id = "Screen_canvas"; + this.screenCanvas.style.cursor = "crosshair"; + this.screenCanvas.onmousemove = (e: MouseEvent) => { + const x = e.clientX; + const y = e.clientY; + this.currentCanvasX = x; + this.currentCanvasY = y; + this.updateXY(); + } + this.screenCanvas.onmouseleave = () => { + this.currentCanvasX = SCREEN_WIDTH; + this.currentCanvasY = SCREEN_HEIGHT; + this.updateXY(); + } + foBody.appendChild(this.screenCanvas); + //foreignObject.appendChild(this.screenCanvas); + + this.screenCanvas.width = SCREEN_WIDTH; + this.screenCanvas.height = SCREEN_HEIGHT; + this.screenCanvasCtx = this.screenCanvas.getContext("2d"); + + this.screenXYText = this.element.getElementById('xyPos') as SVGTextElement; + this.updateXY(); } private attachEvents() { diff --git a/sim/visuals/boardsvg.ts b/sim/visuals/boardsvg.ts index e25f69a9..1a703aca 100644 --- a/sim/visuals/boardsvg.ts +++ b/sim/visuals/boardsvg.ts @@ -9,15 +9,22 @@ namespace pxsim.visuals { xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="169.82979" - height="259.11862" - viewBox="0 0 169.82979 259.11862" + width="99.984344" + height="151.66585" + viewBox="0 0 99.984346 151.66585" id="svg2" version="1.1" inkscape:version="0.91 r13725" sodipodi:docname="board.svg"> + @@ -695,7 +702,7 @@ namespace pxsim.visuals { inkscape:label="Button" inkscape:menu="Bevels" inkscape:menu-tooltip="Soft bevel, slightly depressed middle" - style="color-interpolation-filters:sRGB;" + style="color-interpolation-filters:sRGB" id="filter7573"> image/svg+xml - + @@ -932,10 +939,10 @@ namespace pxsim.visuals { inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" - transform="translate(-286.75886,-393.46077)"> + transform="translate(-321.68157,-447.18716)"> + transform="matrix(0.16751195,0,0,0.16751196,310.76765,431.68528)"> + id="Screen"> + ry="5" + id="rect196" /> + x, y -`; + + +`; } \ No newline at end of file