diff --git a/js/components/MilkdropWindow/index.js b/js/components/MilkdropWindow/index.js new file mode 100644 index 00000000..038c0d9e --- /dev/null +++ b/js/components/MilkdropWindow/index.js @@ -0,0 +1,100 @@ +import React from "react"; +import screenfull from "screenfull"; +import butterchurn from "butterchurn"; +import reactionDiffusion2 from "butterchurn-presets/presets/converted/Geiss - Reaction Diffusion 2"; + +class MilkdropWindow extends React.Component { + constructor() { + super(); + } + componentDidMount() { + const analyserNode = this.props.analyser; + this.visualizer = butterchurn.createVisualizer( + analyserNode.context, + this._canvasNode, + { + width: this._canvasNode.width, + height: this._canvasNode.height, + pixelRatio: window.devicePixelRatio || 1 + } + ); + this.visualizer.connectAudio(analyserNode); + this.visualizer.loadPreset(reactionDiffusion2, 0); + this._renderViz(); + + require.ensure(["butterchurn-presets"], require => { + const butterchurnPresets = require("butterchurn-presets"); + const presets = butterchurnPresets.getPresets(); + const presetKeys = Object.keys(presets); + this.cycleInterval = setInterval(() => { + const presetIdx = Math.floor(presetKeys.length * Math.random()); + const preset = presets[presetKeys[presetIdx]]; + this.visualizer.loadPreset(preset, 2.7); + }, 15000); + }); + } + componentWillUnmount() { + this._pauseViz(); + this._stopCycling(); + } + componentDidUpdate(prevProps) { + if ( + this.props.width !== prevProps.width || + this.props.height !== prevProps.height + ) { + this._setRendererSize(this.props.width, this.props.height); + } + } + _renderViz() { + this.animationFrameRequest = requestAnimationFrame(() => this._renderViz()); + this.visualizer.render(); + } + _pauseViz() { + if (this.animationFrameRequest) { + window.cancelAnimationFrame(this.animationFrameRequest); + this.animationFrameRequest = null; + } + } + _stopCycling() { + if (this.cycleInterval) { + clearInterval(this.cycleInterval); + this.cycleInterval = null; + } + } + _setRendererSize(width, height) { + this._canvasNode.width = width; + this._canvasNode.height = height; + this.visualizer.setRendererSize(width, height); + } + _handleRequestFullsceen() { + if (screenfull.enabled) { + if (!screenfull.isFullscreen) { + screenfull.request(this._canvasNode); + this._setRendererSize(window.innerWidth, window.innerHeight); + } else { + screenfull.exit(); + this._setRendererSize(this.props.width, this.props.height); + } + } + } + render() { + return ( + (this._canvasNode = node)} + onDoubleClick={() => this._handleRequestFullsceen()} + style={{ + position: "absolute", + top: 0, + bottom: 0, + left: 0, + right: 0, + height: "100%", + width: "100%" + }} + /> + ); + } +} + +export default MilkdropWindow; diff --git a/js/index.js b/js/index.js index 8913fa15..c92269c6 100644 --- a/js/index.js +++ b/js/index.js @@ -8,6 +8,7 @@ import visor from "../skins/Vizor1-01.wsz"; import xmms from "../skins/XMMS-Turquoise.wsz"; import zaxon from "../skins/ZaxonRemake1-0.wsz"; import green from "../skins/Green-Dimension-V2.wsz"; +// import MilkdropWindow from "./components/MilkdropWindow"; import Webamp from "./webamp"; import { STEP_MARQUEE, @@ -138,6 +139,12 @@ Raven.context(() => { } ], enableHotkeys: true, + // __extraWindows: [ + // { + // title: "Milkdrop 2", + // Component: MilkdropWindow + // } + // ], __initialState: initialState, __customMiddlewares: [analyticsMiddleware, ravenMiddleware] }); diff --git a/package.json b/package.json index 10caf28a..013438c7 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,8 @@ "babel-plugin-transform-react-jsx": "^6.24.1", "babel-preset-env": "^1.6.1", "babel-runtime": "^6.26.0", + "butterchurn": "^2.2.2", + "butterchurn-presets": "^0.0.2", "cardinal-spline-js": "^2.3.6", "classnames": "^2.2.5", "eslint-plugin-import": "^2.7.0", @@ -95,6 +97,7 @@ "redux-devtools-extension": "^2.13.2", "redux-thunk": "^2.1.0", "reselect": "^3.0.1", + "screenfull": "^3.3.2", "tinyqueue": "^1.2.3", "webpack": "^3.6.0", "webpack-merge": "^4.1.2", diff --git a/yarn.lock b/yarn.lock index 67d7382d..ded0d257 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1197,6 +1197,22 @@ builtin-status-codes@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" +butterchurn-presets@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/butterchurn-presets/-/butterchurn-presets-0.0.2.tgz#9af9c1f0eec6ca99c4e362b5ab2c070537c0b07f" + dependencies: + babel-runtime "^6.26.0" + ecma-proposal-math-extensions "0.0.2" + lodash "^4.17.4" + +butterchurn@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/butterchurn/-/butterchurn-2.2.2.tgz#219f54a2f674179c2ba580ea7002d26d740a31f4" + dependencies: + babel-runtime "^6.26.0" + ecma-proposal-math-extensions "0.0.2" + lodash "^4.17.4" + bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" @@ -2147,6 +2163,10 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" +ecma-proposal-math-extensions@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/ecma-proposal-math-extensions/-/ecma-proposal-math-extensions-0.0.2.tgz#a6a3d64819db70cee0d2e1976b6315d00e4714a0" + ecstatic@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ecstatic/-/ecstatic-3.2.0.tgz#1b1aee1ca7c6b99cfb5cf6c9b26b481b90c4409f" @@ -6405,6 +6425,10 @@ schema-utils@^0.4.5: ajv "^6.1.0" ajv-keywords "^3.1.0" +screenfull@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-3.3.2.tgz#a6adf3b3f5556da812725385880600f5b39fbf25" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"