Sim screen canvas implementation and _setPixel.

This commit is contained in:
Sam El-Husseini 2017-07-12 10:25:17 +03:00
parent 340d5e5cbf
commit 8215e8446a
6 changed files with 197 additions and 38 deletions

View File

@ -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();

View File

@ -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();

34
sim/state/screen.ts Normal file
View File

@ -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) {
}
}

View File

@ -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">
<defs
id="defs4">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 129.55931 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="169.82979 : 129.55931 : 1"
inkscape:persp3d-origin="84.914895 : 86.372875 : 1"
id="perspective4353" />
<linearGradient
inkscape:collect="always"
id="linearGradient7522">
@ -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">
<feGaussianBlur
stdDeviation="0.01"
@ -815,7 +822,7 @@
id="feSpecularLighting4340"
in="result4"
surfaceScale="5"
specularExponent="17.9"
specularExponent="17.89999962"
result="result94">
<feDistantLight
id="feDistantLight4342"
@ -831,7 +838,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="filter4346">
<feGaussianBlur
stdDeviation="0.01"
@ -881,7 +888,7 @@
<feSpecularLighting
in="result4"
surfaceScale="5"
specularExponent="17.9"
specularExponent="17.89999962"
id="feSpecularLighting4368">
<feDistantLight
azimuth="225"
@ -901,11 +908,11 @@
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="3.959798"
inkscape:cx="67.374525"
inkscape:cy="102.35018"
inkscape:zoom="5.6"
inkscape:cx="26.741055"
inkscape:cy="70.052364"
inkscape:document-units="px"
inkscape:current-layer="g7739"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1676"
inkscape:window-height="1005"
@ -925,7 +932,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -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)">
<g
id="g7739"
transform="matrix(0.28940625,0,0,0.28940625,266.4478,365.22322)">
transform="matrix(0.16751195,0,0,0.16751196,310.76765,431.68528)">
<rect
ry="2"
rx="2"
@ -1039,7 +1046,7 @@
style="fill:url(#linearGradient4251);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:20;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<g
id="g5520">
id="Screen">
<g
id="g5516">
<rect
@ -1054,13 +1061,13 @@
</g>
<rect
style="fill:#a0b5a6;fill-opacity:1;stroke:none;stroke-width:20;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="Screen"
width="342.28098"
height="232.08661"
x="192.45197"
y="179.43317"
rx="5"
ry="5" />
ry="5"
id="rect196" />
</g>
<path
sodipodi:nodetypes="ccccccccc"
@ -1174,5 +1181,18 @@
id="tspan5452"
x="-916.42859"
y="1035.2194" /></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:4px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#7f8c8d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="385"
y="507.42444"
id="xyPos"
sodipodi:linespacing="125%"
inkscape:label="#text4342"><tspan
sodipodi:role="line"
id="tspan4344"
x="393.64587"
y="507.42444"
style="font-size:3.75px">x, y</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

@ -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() {

View File

@ -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">
<defs
id="defs4">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 129.55931 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="169.82979 : 129.55931 : 1"
inkscape:persp3d-origin="84.914895 : 86.372875 : 1"
id="perspective4353" />
<linearGradient
inkscape:collect="always"
id="linearGradient7522">
@ -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">
<feGaussianBlur
stdDeviation="0.01"
@ -814,7 +821,7 @@ namespace pxsim.visuals {
id="feSpecularLighting4340"
in="result4"
surfaceScale="5"
specularExponent="17.9"
specularExponent="17.89999962"
result="result94">
<feDistantLight
id="feDistantLight4342"
@ -830,7 +837,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="filter4346">
<feGaussianBlur
stdDeviation="0.01"
@ -880,7 +887,7 @@ namespace pxsim.visuals {
<feSpecularLighting
in="result4"
surfaceScale="5"
specularExponent="17.9"
specularExponent="17.89999962"
id="feSpecularLighting4368">
<feDistantLight
azimuth="225"
@ -900,11 +907,11 @@ namespace pxsim.visuals {
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="1.979899"
inkscape:cx="67.374525"
inkscape:cy="102.35018"
inkscape:zoom="5.6"
inkscape:cx="26.741055"
inkscape:cy="70.052364"
inkscape:document-units="px"
inkscape:current-layer="g7739"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1676"
inkscape:window-height="1005"
@ -924,7 +931,7 @@ namespace pxsim.visuals {
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -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)">
<g
id="g7739"
transform="matrix(0.28940625,0,0,0.28940625,266.4478,365.22322)">
transform="matrix(0.16751195,0,0,0.16751196,310.76765,431.68528)">
<rect
ry="2"
rx="2"
@ -1038,7 +1045,7 @@ namespace pxsim.visuals {
style="fill:url(#linearGradient4251);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:20;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
<g
id="g5520">
id="Screen">
<g
id="g5516">
<rect
@ -1053,13 +1060,13 @@ namespace pxsim.visuals {
</g>
<rect
style="fill:#a0b5a6;fill-opacity:1;stroke:none;stroke-width:20;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="Screen"
width="342.28098"
height="232.08661"
x="192.45197"
y="179.43317"
rx="5"
ry="5" />
ry="5"
id="rect196" />
</g>
<path
sodipodi:nodetypes="ccccccccc"
@ -1173,6 +1180,21 @@ namespace pxsim.visuals {
id="tspan5452"
x="-916.42859"
y="1035.2194" /></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:4px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#7f8c8d;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="385"
y="507.42444"
id="xyPos"
sodipodi:linespacing="125%"
inkscape:label="#text4342"><tspan
sodipodi:role="line"
id="tspan4344"
x="393.64587"
y="507.42444"
style="font-size:3.75px">x, y</tspan></text>
</g>
</svg>`;
</svg>
`;
}