From e8eddd62ff855c8c3342d2926c7422bfd4b70f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Silvani?= Date: Thu, 27 Aug 2020 16:13:02 -0300 Subject: [PATCH 1/8] Add vedajs dependency --- packages/web/package.json | 1 + yarn.lock | 50 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/packages/web/package.json b/packages/web/package.json index 00b5f007..54105f64 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -33,6 +33,7 @@ "react": "^16.12.0", "react-dom": "^16.12.0", "simple-peer": "^9.6.2", + "vedajs": "^0.15.0", "ws": "^7.0.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 8b39be45..64db9eb5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -995,6 +995,11 @@ unique-filename "^1.1.1" which "^1.3.1" +"@fand/gifuct-js@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@fand/gifuct-js/-/gifuct-js-1.0.0.tgz#8e001acdc20b74222805360d42c702409b9e0321" + integrity sha512-8jduCVQcvK7L9O+1q/DL/AYPW+PYm4glkS7hkLE9+GSUABfVj62MJv6EbHY6PNbbvyYx8voDLmvB5ppQoIyF9g== + "@fortawesome/fontawesome-common-types@^0.2.27": version "0.2.27" resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.27.tgz#19706345859fc46adf3684ed01d11b40903b87e9" @@ -6070,6 +6075,13 @@ is-utf8@^0.2.0: resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= +is-video@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-video/-/is-video-1.0.1.tgz#7bc67760b0103d402bc1f10bb542f16a3687773b" + integrity sha1-e8Z3YLAQPUArwfELtULxajaHdzs= + dependencies: + video-extensions "^1.0.0" + is-windows@^1.0.0, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -10350,11 +10362,33 @@ thread-loader@2.1.3: loader-utils "^1.1.0" neo-async "^2.6.0" +three-mtl-loader@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/three-mtl-loader/-/three-mtl-loader-1.0.2.tgz#d0060f1afb8bc2c166ea56cebad250d73da18563" + integrity sha512-GqDrWC5rbi+0/gp999S4lpCSHroBEfe9NqmH165orG0QhXeknL/eSNVMJUWBNgg2sBW7vlqVNWD/P0kdHeGC9g== + dependencies: + three "^0.87.1" + +three-obj-loader@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/three-obj-loader/-/three-obj-loader-1.1.3.tgz#4d540a256fcf2a59a6c6e0cd51a623efd76fd87d" + integrity sha512-usuOOTAqeM7J7dyae/I9ltFnfy1g47Hsr3byTvBTeH9LYz5vb2i8rLd2Hi1HEr0MbB5H4p9YrqFaDGcijXEVNw== + +three@^0.100.0: + version "0.100.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.100.0.tgz#262841c0b7d88ebd62af73f28d9f578963b3aa00" + integrity sha512-/lN2rdE1OqIwJr4/HcSaOisiCY0uVA0sqPpbCG5nil2uICEdS0LfGwSVYTtZDsIpR76r3++h5H3Hzg5D+SJBRQ== + three@^0.101.0: version "0.101.1" resolved "https://registry.yarnpkg.com/three/-/three-0.101.1.tgz#e7681ef52f4e572cb84f307f16f540c457030ec6" integrity sha512-8ufimUVmRLtH+BTpEIbDjdGEKQOVWLMLgGynaKin1KbYTE136ZNOepJ8EgByi0tN43dQ7B1YrKLCJgXGy4bLmw== +three@^0.87.1: + version "0.87.1" + resolved "https://registry.yarnpkg.com/three/-/three-0.87.1.tgz#466a34edc4543459ced9b9d7d276b65216fe2ba8" + integrity sha1-Rmo07cRUNFnO2bnX0na2Uhb+K6g= + through2@^2.0.0, through2@^2.0.2: version "2.0.5" resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" @@ -10794,6 +10828,17 @@ vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= +vedajs@^0.15.0: + version "0.15.0" + resolved "https://registry.yarnpkg.com/vedajs/-/vedajs-0.15.0.tgz#28af980567994eda2ea9a8cdacea6c04246fffa1" + integrity sha512-PH5iYqX1gFtAyD8IKh8mBHe3QkgbBNeJdOx3pUXmrGdFULRcFXuAHHen1CTwD/4QvLcziJDy/8AYbN2jkHyB0A== + dependencies: + "@fand/gifuct-js" "^1.0.0" + is-video "^1.0.1" + three "^0.100.0" + three-mtl-loader "^1.0.2" + three-obj-loader "^1.1.3" + verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -10803,6 +10848,11 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +video-extensions@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/video-extensions/-/video-extensions-1.1.0.tgz#eaa86b45f29a853c2b873e9d8e23b513712997d6" + integrity sha1-6qhrRfKahTwrhz6djiO1E3Epl9Y= + vm-browserify@^1.0.1: version "1.1.2" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" From 0e680b6a1c18aee1d7cba03ca5cdb2d2e264d838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Silvani?= Date: Thu, 27 Aug 2020 16:15:47 -0300 Subject: [PATCH 2/8] Only render HydraCanvas and HydraError components if hydra is enabled on session --- packages/web/pages/s/[session].tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/pages/s/[session].tsx b/packages/web/pages/s/[session].tsx index fdf311c8..579998b2 100644 --- a/packages/web/pages/s/[session].tsx +++ b/packages/web/pages/s/[session].tsx @@ -365,7 +365,7 @@ class SessionPage extends Component { hasWebGl={hasWebGl} /> )} - {hasWebgl && ( + {hasWebgl && hasHydraSlot && ( <> {hydraError && {hydraError}} From 4d7f5eca4fc9509eb35620e9746ce330ee7dae57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Silvani?= Date: Thu, 27 Aug 2020 16:54:12 -0300 Subject: [PATCH 3/8] Add classnames dep --- packages/web/package.json | 1 + yarn.lock | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/packages/web/package.json b/packages/web/package.json index 54105f64..4150d927 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -23,6 +23,7 @@ "@fortawesome/react-fontawesome": "^0.1.8", "@zeit/next-css": "^1.0.1", "@zeit/next-sass": "^1.0.1", + "classnames": "^2.2.6", "commander": "^2.20.0", "cross-env": "^7.0.0", "express": "^4.17.1", diff --git a/yarn.lock b/yarn.lock index 64db9eb5..69de42fa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3181,6 +3181,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +classnames@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== + cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" From c935ddb4530b4f31eaf0720af34af8a3877bc610 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dami=C3=A1n=20Silvani?= Date: Thu, 27 Aug 2020 19:33:16 -0300 Subject: [PATCH 4/8] Experimental VEDA.js support Only fragment shaders; incompatible with session using Hydra. --- README.md | 2 +- packages/web/components/HydraCanvas.tsx | 38 ------ packages/web/components/Session.tsx | 7 +- packages/web/components/TextEditor.tsx | 1 + packages/web/lib/VedaWrapper.ts | 22 ++++ packages/web/pages/s/[session].tsx | 166 +++++++++++++++++++----- packages/web/tsconfig.json | 15 ++- 7 files changed, 178 insertions(+), 73 deletions(-) delete mode 100644 packages/web/components/HydraCanvas.tsx create mode 100644 packages/web/lib/VedaWrapper.ts diff --git a/README.md b/README.md index d5933b49..71a4aae6 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Web-based P2P collaborative editor for live coding music and graphics * Web Plugins, for languages embedded in editor: - [Hydra](https://github.com/ojack/hydra) - [p5.js](https://p5js.org/) - - [VEDA.js](https://github.com/fand/vedajs) (*not implemented yet*) + - [VEDA.js](https://github.com/fand/vedajs) - [Tilt](https://github.com/munshkr/tilt) (*not implemented yet*) diff --git a/packages/web/components/HydraCanvas.tsx b/packages/web/components/HydraCanvas.tsx deleted file mode 100644 index c8370edd..00000000 --- a/packages/web/components/HydraCanvas.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React, { memo } from "react"; - -type Props = { - fullscreen?: boolean; -}; - -const HydraCanvas = React.forwardRef( - (props: Props, ref: React.RefObject) => { - const { fullscreen } = props; - const className: string = fullscreen ? "fullscreen" : ""; - - console.log("Hydra canvas rendered"); - - return ( - <> - - - - ); - } -); - -export default memo(HydraCanvas); diff --git a/packages/web/components/Session.tsx b/packages/web/components/Session.tsx index 1ddccaec..8c12f4fd 100644 --- a/packages/web/components/Session.tsx +++ b/packages/web/components/Session.tsx @@ -7,13 +7,14 @@ import Mosaic from "./Mosaic"; import Audio from "./Audio"; const MAX_LINES: number = 100; -const LOCAL_TARGETS = ["hydra"]; +const LOCAL_TARGETS = ["hydra", "veda"]; type Props = { websocketsHost: string; sessionName: string; userName?: string; onHydraEvaluation: (code: string) => void; + onVedaEvaluation: (code: string) => void; audioStreamingEnabled: boolean; extraIceServers?: IceServerType[]; layout: { @@ -46,6 +47,7 @@ class Session extends Component { static defaultProps = { userName: "anonymous", onHydraEvaluation: () => {}, + onVedaEvaluation: () => {}, }; componentDidMount() { @@ -141,6 +143,9 @@ class Session extends Component { case "hydra": this.props.onHydraEvaluation(body); break; + case "veda": + this.props.onVedaEvaluation(body); + break; default: console.error("Unhandle local target:", target); } diff --git a/packages/web/components/TextEditor.tsx b/packages/web/components/TextEditor.tsx index 84df5dea..2c82f77b 100644 --- a/packages/web/components/TextEditor.tsx +++ b/packages/web/components/TextEditor.tsx @@ -54,6 +54,7 @@ const modesByTarget = { foxdot: "python", sclang: "smalltalk", hydra: "javascript", + veda: "javascript", }; const EvaluateButton = ({ onClick }) => ( diff --git a/packages/web/lib/VedaWrapper.ts b/packages/web/lib/VedaWrapper.ts new file mode 100644 index 00000000..3f7b3bca --- /dev/null +++ b/packages/web/lib/VedaWrapper.ts @@ -0,0 +1,22 @@ +import Veda from "vedajs"; + +class VedaWrapper { + veda: Veda; + + constructor(canvas: HTMLCanvasElement) { + this.veda = new Veda(); + this.veda.setCanvas(canvas); + } + + evalFragment(code: string) { + this.veda.loadFragmentShader(code); + this.veda.play(); + } + + evalVertex(code: string) { + this.veda.loadVertexShader(code); + this.veda.play(); + } +} + +export default VedaWrapper; diff --git a/packages/web/pages/s/[session].tsx b/packages/web/pages/s/[session].tsx index 579998b2..e7cad4ff 100644 --- a/packages/web/pages/s/[session].tsx +++ b/packages/web/pages/s/[session].tsx @@ -8,7 +8,7 @@ import Layout from "../../components/Layout"; import Session from "../../components/Session"; import { IceServerType } from "../../lib/SessionClient"; import HydraWrapper from "../../lib/HydraWrapper"; -import HydraCanvas from "../../components/HydraCanvas"; +import VedaWrapper from "../../lib/VedaWrapper"; import HydraError from "../../components/HydraError"; const defaultLayoutList = ["tidal", "hydra"]; @@ -41,23 +41,32 @@ const extraIceServers = (() => { return res; })(); -class JoinSessionForm extends Component<{ +interface JoinSessionFormProps { username: string; onSubmit: Function; hydraVisible: boolean; + vedaVisible: boolean; hasWebGl: boolean; -}> { - state = { - username: null, - hydraEnabled: true, - audioStreamingEnabled: false, - }; +} +interface JoinSessionFormState { + hydraEnabled: boolean; + vedaEnabled: boolean; + audioStreamingEnabled: boolean; + username: string; +} + +class JoinSessionForm extends Component< + JoinSessionFormProps, + JoinSessionFormState +> { constructor(props) { super(props); this.state = { - ...this.state, + hydraEnabled: props.hydraVisible, + vedaEnabled: props.vedaVisible, + audioStreamingEnabled: false, username: props.username || "", }; } @@ -72,6 +81,11 @@ class JoinSessionForm extends Component<{ this.setState({ hydraEnabled: target.checked }); }; + handleChangeVedaCheckbox = (e: ChangeEvent) => { + const target = e.target as HTMLInputElement; + this.setState({ vedaEnabled: target.checked }); + }; + handleChangeAudioStreamingCheckbox = (e: ChangeEvent) => { const target = e.target as HTMLInputElement; this.setState({ audioStreamingEnabled: target.checked }); @@ -82,15 +96,25 @@ class JoinSessionForm extends Component<{ const { onSubmit } = this.props; - let { username, hydraEnabled, audioStreamingEnabled } = this.state; + let { + username, + hydraEnabled, + vedaEnabled, + audioStreamingEnabled, + } = this.state; if (!username) username = "anonymous"; - onSubmit({ username, hydraEnabled, audioStreamingEnabled }); + onSubmit({ username, hydraEnabled, vedaEnabled, audioStreamingEnabled }); }; render() { - const { hydraVisible, hasWebGl } = this.props; - const { username, hydraEnabled, audioStreamingEnabled } = this.state; + const { hydraVisible, vedaVisible, hasWebGl } = this.props; + const { + username, + hydraEnabled, + vedaEnabled, + audioStreamingEnabled, + } = this.state; return (
@@ -130,6 +154,28 @@ class JoinSessionForm extends Component<{ )} + {vedaVisible && ( +
+
+ +
+
+ )} +