Sim screen canvas implementation and _setPixel.
This commit is contained in:
parent
340d5e5cbf
commit
8215e8446a
@ -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();
|
||||
|
||||
|
@ -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
34
sim/state/screen.ts
Normal 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) {
|
||||
|
||||
}
|
||||
}
|
@ -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 |
@ -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() {
|
||||
|
@ -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>
|
||||
|
||||
`;
|
||||
}
|
Loading…
Reference in New Issue
Block a user