From 974638f2111985949775ea19fc16be407291fedb Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Sat, 28 Mar 2020 14:11:31 -0700 Subject: [PATCH 1/6] Basic implementation of neopixel --- .vscode/settings.json | 7 +++++- package.json | 2 +- src/view/components/clue/ClueImage.tsx | 2 ++ src/view/components/clue/ClueSimulator.tsx | 26 +++++++++++++++++----- src/view/components/clue/Clue_svg.tsx | 16 +++++++++++-- 5 files changed, 43 insertions(+), 10 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index fa0a10487..2b8373f56 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,5 +7,10 @@ "out": true // set this to false to include "out" folder in search results }, // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off" + "typescript.tsc.autoDetect": "off", + "python.linting.pylintArgs": [ + "--init-hook", + "import sys; sys.path.append(\"\"/Users/kevin/.vscode/extensions/ms-python.devicesimulatorexpress-2020.0.35773/out\"\")" + ], + "python.pythonPath": "venv/bin/python3" } diff --git a/package.json b/package.json index 9ba36b931..789258b71 100644 --- a/package.json +++ b/package.json @@ -354,4 +354,4 @@ "extensionDependencies": [ "ms-python.python" ] -} \ No newline at end of file +} diff --git a/src/view/components/clue/ClueImage.tsx b/src/view/components/clue/ClueImage.tsx index 00e0d9a3b..a104108f0 100644 --- a/src/view/components/clue/ClueImage.tsx +++ b/src/view/components/clue/ClueImage.tsx @@ -17,6 +17,7 @@ interface EventTriggers { interface IProps { eventTriggers: EventTriggers; displayMessage: string; + neopixel:number[] } const BUTTON_CLASSNAME = { @@ -85,6 +86,7 @@ export class ClueImage extends React.Component { ); } diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 9e1c87840..fae8bce6a 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -15,6 +15,7 @@ import { BUTTONS_KEYS, ClueImage } from "./ClueImage"; const DEFAULT_CLUE_STATE: IClueState = { buttons: { button_a: false, button_b: false }, displayMessage: DEFAULT_IMG_CLUE, + neopixel: [0, 0, 0] }; interface IState { @@ -29,6 +30,7 @@ interface IState { interface IClueState { buttons: { button_a: boolean; button_b: boolean }; displayMessage: string; + neopixel: number[] } export class ClueSimulator extends React.Component { private imageRef: React.RefObject = React.createRef(); @@ -55,12 +57,23 @@ export class ClueSimulator extends React.Component { }); break; case "set-state": - this.setState({ - clue: { - ...this.state.clue, - displayMessage: message.state.display_base64, - }, - }); + console.log(`message received ${JSON.stringify(message.state)}`) + if (message.state.display_base64) { + this.setState({ + clue: { + ...this.state.clue, + displayMessage: message.state.display_base64, + }, + }) + } else if (message.state.pixels) { + this.setState({ + clue: { + ...this.state.clue, + neopixel: message.state.pixels, + }, + }) + }; + break; case "activate-play": const newRunningFile = this.state.currently_selected_file; @@ -121,6 +134,7 @@ export class ClueSimulator extends React.Component { onKeyEvent: this.onKeyEvent, }} displayMessage={this.state.clue.displayMessage} + neopixel={this.state.clue.neopixel} /> { private svgRef: React.RefObject = React.createRef(); + private neopixel: React.RefObject = React.createRef() private buttonRefs: IRefObject = { BTN_A: React.createRef(), @@ -35,6 +37,7 @@ export class ClueSvg extends React.Component { } componentDidUpdate() { this.updateDisplay(); + this.updateNeopixel() } render() { @@ -42,7 +45,7 @@ export class ClueSvg extends React.Component {
{ y={28} width={176} height={152} - href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQICAQEBAQMCAgICAwMEBAMDAwMEBAYFBAQFBAMDBQcFBQYGBgYGBAUHBwcGBwYGBgb/2wBDAQEBAQEBAQMCAgMGBAMEBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgb/wAARCAJYAlgDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD/AD/6KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP//Z" /> { rx="18.28" /> +
); @@ -949,4 +952,13 @@ export class ClueSvg extends React.Component { ); } } + private updateNeopixel() { + const { neopixel } = this.props + if (this.neopixel.current) { + const rgbColor = `rgb(${neopixel[0]},${neopixel[1]},${neopixel[2]})` + console.log(rgbColor) + this.neopixel.current.setAttribute('fill', rgbColor) + } + + } } From efe32bb4b1b5553e49b69761a35672f2bd880553 Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Sat, 28 Mar 2020 14:48:31 -0700 Subject: [PATCH 2/6] Add basic gradient for effect --- src/view/components/clue/Clue_svg.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index ab426ebea..3750fea55 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -14,6 +14,7 @@ interface IProps { export class ClueSvg extends React.Component { private svgRef: React.RefObject = React.createRef(); private neopixel: React.RefObject = React.createRef() + private pixelStopGradient: React.RefObject = React.createRef() private buttonRefs: IRefObject = { BTN_A: React.createRef(), @@ -52,7 +53,11 @@ export class ClueSvg extends React.Component { width="100%" height="100%" > - + + + + + { rx="18.28" /> + @@ -954,11 +960,15 @@ export class ClueSvg extends React.Component { } private updateNeopixel() { const { neopixel } = this.props + const rgbColor = `rgb(${neopixel[0]},${neopixel[1]},${neopixel[2]})` + if (this.neopixel.current) { - const rgbColor = `rgb(${neopixel[0]},${neopixel[1]},${neopixel[2]})` console.log(rgbColor) this.neopixel.current.setAttribute('fill', rgbColor) } + if (this.pixelStopGradient.current) { + this.pixelStopGradient.current.setAttribute('stop-color', rgbColor) + } } } From 2dba715fdc7446c8c4cd03249a21f3f9c28e6d2a Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Sat, 28 Mar 2020 15:19:39 -0700 Subject: [PATCH 3/6] Remove gradient if led is off --- src/view/components/clue/ClueSimulator.tsx | 2 +- src/view/components/clue/Clue_svg.tsx | 25 ++++++++++++++++------ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index fae8bce6a..7c2c3d932 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -12,7 +12,7 @@ import { sendMessage } from "../../utils/MessageUtils"; import ActionBar from "../simulator/ActionBar"; import { BUTTONS_KEYS, ClueImage } from "./ClueImage"; -const DEFAULT_CLUE_STATE: IClueState = { +export const DEFAULT_CLUE_STATE: IClueState = { buttons: { button_a: false, button_b: false }, displayMessage: DEFAULT_IMG_CLUE, neopixel: [0, 0, 0] diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index 3750fea55..50eccbd8a 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -3,6 +3,7 @@ import * as React from "react"; import "../../styles/Clue.css"; +import { DEFAULT_CLUE_STATE } from "./ClueSimulator"; export interface IRefObject { [key: string]: React.RefObject; } @@ -10,7 +11,7 @@ interface IProps { displayImage: string; neopixel: number[] } - +const LED_TINT_FACTOR = 0.5 export class ClueSvg extends React.Component { private svgRef: React.RefObject = React.createRef(); private neopixel: React.RefObject = React.createRef() @@ -35,6 +36,8 @@ export class ClueSvg extends React.Component { } componentDidMount() { this.updateDisplay(); + this.updateNeopixel() + } componentDidUpdate() { this.updateDisplay(); @@ -46,7 +49,7 @@ export class ClueSvg extends React.Component {
{ > - + @@ -944,8 +947,8 @@ export class ClueSvg extends React.Component { rx="18.28" /> - - + +
); @@ -960,13 +963,21 @@ export class ClueSvg extends React.Component { } private updateNeopixel() { const { neopixel } = this.props - const rgbColor = `rgb(${neopixel[0]},${neopixel[1]},${neopixel[2]})` + const rgbColor = `rgb(${neopixel[0] + (255 - neopixel[0]) * LED_TINT_FACTOR}, + ${neopixel[1] + (255 - neopixel[1]) * LED_TINT_FACTOR},${neopixel[2] + (255 - neopixel[2]) * LED_TINT_FACTOR})` if (this.neopixel.current) { - console.log(rgbColor) this.neopixel.current.setAttribute('fill', rgbColor) } if (this.pixelStopGradient.current) { + if (neopixel === DEFAULT_CLUE_STATE.neopixel) { + console.log("remove opacity") + + this.pixelStopGradient.current.setAttribute('stop-opacity', '0') + } else { + this.pixelStopGradient.current.setAttribute('stop-opacity', '1') + + } this.pixelStopGradient.current.setAttribute('stop-color', rgbColor) } From 46d8dbc95367cb58ad3915408ae30be5b9c908cf Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Sun, 29 Mar 2020 13:55:29 -0700 Subject: [PATCH 4/6] Positioning and styling for neopixel --- src/view/components/clue/Clue_svg.tsx | 11 +++++++---- src/view/styles/Clue.css | 4 ++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index 50eccbd8a..9b14a66b3 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -319,8 +319,8 @@ export class ClueSvg extends React.Component { - - + + { rx="18.28" /> - - + + Neopixel + + + ); diff --git a/src/view/styles/Clue.css b/src/view/styles/Clue.css index 45a9e3d92..c252fb62b 100644 --- a/src/view/styles/Clue.css +++ b/src/view/styles/Clue.css @@ -129,3 +129,7 @@ .cls-22 { stroke: #7e7272; } +.sim-text-outside { + font-size: 14px; + fill: var(--vscode-descriptionForeground); +} \ No newline at end of file From 248ccc2d21a0710901903831f13e136c33980f2a Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Tue, 31 Mar 2020 12:48:40 -0700 Subject: [PATCH 5/6] Clean up branch with feedback --- .vscode/settings.json | 8 +-- src/base_circuitpython/neopixel_write.py | 4 -- src/view/components/clue/ClueImage.tsx | 2 +- src/view/components/clue/ClueSimulator.tsx | 14 +++-- src/view/components/clue/Clue_svg.tsx | 67 ++++++++++++++-------- src/view/constants.ts | 1 + src/view/styles/Clue.css | 4 +- src/view/styles/Microbit.css | 2 +- 8 files changed, 58 insertions(+), 44 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2b8373f56..0b79e8a23 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,12 +5,6 @@ }, "search.exclude": { "out": true // set this to false to include "out" folder in search results - }, + } // Turn off tsc task auto detection since we have the necessary tasks as npm scripts - "typescript.tsc.autoDetect": "off", - "python.linting.pylintArgs": [ - "--init-hook", - "import sys; sys.path.append(\"\"/Users/kevin/.vscode/extensions/ms-python.devicesimulatorexpress-2020.0.35773/out\"\")" - ], - "python.pythonPath": "venv/bin/python3" } diff --git a/src/base_circuitpython/neopixel_write.py b/src/base_circuitpython/neopixel_write.py index 450b40aa3..8862863e8 100644 --- a/src/base_circuitpython/neopixel_write.py +++ b/src/base_circuitpython/neopixel_write.py @@ -30,10 +30,6 @@ def neopixel_write(gpio, buf): def send_clue(buf): sendable_json = {CONSTANTS.PIXELS: tuple(buf)} - - # for now, just print pixels - print(sendable_json) - utils.send_to_simulator(sendable_json, CONSTANTS.CLUE) diff --git a/src/view/components/clue/ClueImage.tsx b/src/view/components/clue/ClueImage.tsx index a104108f0..6d74a2781 100644 --- a/src/view/components/clue/ClueImage.tsx +++ b/src/view/components/clue/ClueImage.tsx @@ -17,7 +17,7 @@ interface EventTriggers { interface IProps { eventTriggers: EventTriggers; displayMessage: string; - neopixel:number[] + neopixel: number[]; } const BUTTON_CLASSNAME = { diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 7c2c3d932..73d552763 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -15,7 +15,7 @@ import { BUTTONS_KEYS, ClueImage } from "./ClueImage"; export const DEFAULT_CLUE_STATE: IClueState = { buttons: { button_a: false, button_b: false }, displayMessage: DEFAULT_IMG_CLUE, - neopixel: [0, 0, 0] + neopixel: [0, 0, 0], }; interface IState { @@ -30,7 +30,7 @@ interface IState { interface IClueState { buttons: { button_a: boolean; button_b: boolean }; displayMessage: string; - neopixel: number[] + neopixel: number[]; } export class ClueSimulator extends React.Component { private imageRef: React.RefObject = React.createRef(); @@ -57,22 +57,24 @@ export class ClueSimulator extends React.Component { }); break; case "set-state": - console.log(`message received ${JSON.stringify(message.state)}`) + console.log( + `message received ${JSON.stringify(message.state)}` + ); if (message.state.display_base64) { this.setState({ clue: { ...this.state.clue, displayMessage: message.state.display_base64, }, - }) + }); } else if (message.state.pixels) { this.setState({ clue: { ...this.state.clue, neopixel: message.state.pixels, }, - }) - }; + }); + } break; case "activate-play": diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index 9b14a66b3..6a8351d5e 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -4,18 +4,20 @@ import * as React from "react"; import "../../styles/Clue.css"; import { DEFAULT_CLUE_STATE } from "./ClueSimulator"; +import CONSTANTS from "../../constants"; export interface IRefObject { [key: string]: React.RefObject; } interface IProps { displayImage: string; - neopixel: number[] + neopixel: number[]; } -const LED_TINT_FACTOR = 0.5 export class ClueSvg extends React.Component { private svgRef: React.RefObject = React.createRef(); - private neopixel: React.RefObject = React.createRef() - private pixelStopGradient: React.RefObject = React.createRef() + private neopixel: React.RefObject = React.createRef(); + private pixelStopGradient: React.RefObject< + SVGStopElement + > = React.createRef(); private buttonRefs: IRefObject = { BTN_A: React.createRef(), @@ -36,12 +38,11 @@ export class ClueSvg extends React.Component { } componentDidMount() { this.updateDisplay(); - this.updateNeopixel() - + this.updateNeopixel(); } componentDidUpdate() { this.updateDisplay(); - this.updateNeopixel() + this.updateNeopixel(); } render() { @@ -56,11 +57,24 @@ export class ClueSvg extends React.Component { width="100%" height="100%" > - - - + + + - + + { Neopixel - + ); } + private updateDisplay() { if (this.displayRef.current && this.props.displayImage) { this.displayRef.current.setAttribute( @@ -964,25 +979,31 @@ export class ClueSvg extends React.Component { ); } } + private updateNeopixel() { - const { neopixel } = this.props - const rgbColor = `rgb(${neopixel[0] + (255 - neopixel[0]) * LED_TINT_FACTOR}, - ${neopixel[1] + (255 - neopixel[1]) * LED_TINT_FACTOR},${neopixel[2] + (255 - neopixel[2]) * LED_TINT_FACTOR})` + const { neopixel } = this.props; + const rgbColor = `rgb(${neopixel[0] + + (255 - neopixel[0]) * CONSTANTS.LED_TINT_FACTOR}, + ${neopixel[1] + + (255 - neopixel[1]) * CONSTANTS.LED_TINT_FACTOR},${neopixel[2] + + (255 - neopixel[2]) * CONSTANTS.LED_TINT_FACTOR})`; if (this.neopixel.current) { - this.neopixel.current.setAttribute('fill', rgbColor) + this.neopixel.current.setAttribute("fill", rgbColor); } if (this.pixelStopGradient.current) { if (neopixel === DEFAULT_CLUE_STATE.neopixel) { - console.log("remove opacity") - - this.pixelStopGradient.current.setAttribute('stop-opacity', '0') + this.pixelStopGradient.current.setAttribute( + "stop-opacity", + "0" + ); } else { - this.pixelStopGradient.current.setAttribute('stop-opacity', '1') - + this.pixelStopGradient.current.setAttribute( + "stop-opacity", + "1" + ); } - this.pixelStopGradient.current.setAttribute('stop-color', rgbColor) + this.pixelStopGradient.current.setAttribute("stop-color", rgbColor); } - } } diff --git a/src/view/constants.ts b/src/view/constants.ts index 933253e2b..5969a8275 100644 --- a/src/view/constants.ts +++ b/src/view/constants.ts @@ -46,6 +46,7 @@ export const CONSTANTS = { "The simulator will run the .py file you have focused on.", SIMULATOR_BUTTON_WIDTH: 60, TOOLBAR_INFO: `Explore what's on the board:`, + LED_TINT_FACTOR: 0.5, }; export const AB_BUTTONS_KEYS = { BTN_A: "BTN_A", diff --git a/src/view/styles/Clue.css b/src/view/styles/Clue.css index c252fb62b..db64fe630 100644 --- a/src/view/styles/Clue.css +++ b/src/view/styles/Clue.css @@ -131,5 +131,5 @@ } .sim-text-outside { font-size: 14px; - fill: var(--vscode-descriptionForeground); -} \ No newline at end of file + fill: var(--vscode-foreground); +} diff --git a/src/view/styles/Microbit.css b/src/view/styles/Microbit.css index f96655fa0..44aed7e9a 100644 --- a/src/view/styles/Microbit.css +++ b/src/view/styles/Microbit.css @@ -24,7 +24,7 @@ svg.sim.grayscale { } .sim-text-outside { font-size: 25px; - fill: var(--vscode-descriptionForeground); + fill: var(--vscode-foreground); } .sim-board, .sim-display, From f23844d3fb1d0e77ebdb1544a325aa93b603805d Mon Sep 17 00:00:00 2001 From: xnkevinnguyen Date: Tue, 31 Mar 2020 12:51:48 -0700 Subject: [PATCH 6/6] Lint files --- src/view/components/clue/ClueSimulator.tsx | 2 +- src/view/components/clue/Clue_svg.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/view/components/clue/ClueSimulator.tsx b/src/view/components/clue/ClueSimulator.tsx index 73d552763..3a9e938df 100644 --- a/src/view/components/clue/ClueSimulator.tsx +++ b/src/view/components/clue/ClueSimulator.tsx @@ -3,8 +3,8 @@ import { AB_BUTTONS_KEYS, // DEVICE_LIST_KEY, CONSTANTS, - WEBVIEW_MESSAGES, DEFAULT_IMG_CLUE, + WEBVIEW_MESSAGES, } from "../../constants"; import PlayLogo from "../../svgs/play_svg"; import StopLogo from "../../svgs/stop_svg"; diff --git a/src/view/components/clue/Clue_svg.tsx b/src/view/components/clue/Clue_svg.tsx index 6a8351d5e..e54c55c47 100644 --- a/src/view/components/clue/Clue_svg.tsx +++ b/src/view/components/clue/Clue_svg.tsx @@ -2,9 +2,9 @@ // Licensed under the MIT license. import * as React from "react"; +import CONSTANTS from "../../constants"; import "../../styles/Clue.css"; import { DEFAULT_CLUE_STATE } from "./ClueSimulator"; -import CONSTANTS from "../../constants"; export interface IRefObject { [key: string]: React.RefObject; }