diff --git a/examples/assets/sounds/folk.mp3 b/examples/assets/sounds/folk.mp3 new file mode 100644 index 000000000..7917a4454 Binary files /dev/null and b/examples/assets/sounds/folk.mp3 differ diff --git a/examples/whs-module-audio/positional/index.pug b/examples/whs-module-audio/positional/index.pug new file mode 100644 index 000000000..33f22e9d6 --- /dev/null +++ b/examples/whs-module-audio/positional/index.pug @@ -0,0 +1,5 @@ +extends ../../layout.pug + +block additional + script(src='../../assets/modules/StatsModule.js') + script(src='../../../modules/whs-module-audio/build/AudioModule.js') diff --git a/examples/whs-module-audio/positional/script.js b/examples/whs-module-audio/positional/script.js new file mode 100644 index 000000000..f20d876ef --- /dev/null +++ b/examples/whs-module-audio/positional/script.js @@ -0,0 +1,86 @@ +import * as UTILS from '../../globals'; + +const controlsModule = new WHS.controls.OrbitModule(); + +const cameraModule = new WHS.app.CameraModule({ + position: { + z: 250, + y: 100 + }, + + far: 30000, + near: 1 +}); + +const world = new WHS.App([ + ...UTILS.appModules({ + position: new THREE.Vector3(0, 10, 200) + }), + + controlsModule, + cameraModule +]); + +controlsModule.controls.autoRotate = true; + +const audioModule = new AudioModule({ + loop: true +}); + +const sphere = new WHS.Sphere({ + geometry: { + radius: 20 + }, + + shadow: { + cast: false + }, + + material: new THREE.MeshBasicMaterial({ + color: 0xffffff + }), + + modules: [ + audioModule + ], + + position: { + y: 5 + } + +}); +sphere.addTo(world); + +audioModule.addListener(cameraModule.camera); +audioModule.playAudio(`${process.assetsPath}/sounds/folk.mp3`); + +new WHS.PointLight({ + light: { + color: 0xffffff, + intensity: 1, + distance: 1000 + }, + + position: [10, 40, 10] +}).addTo(world); + +new WHS.Box({ + geometry: { + width: 2000, + height: 0.1, + depth: 2000 + }, + + shadow: { + cast: false + }, + + material: new THREE.MeshPhongMaterial({ + color: 0xffffff + }), + + position: [0, -60, 0], + rotation: [0, 0, 25] +}).addTo(world); + +world.start(); diff --git a/gulp/dev.js b/gulp/dev.js index c8601cf32..610ce75bd 100644 --- a/gulp/dev.js +++ b/gulp/dev.js @@ -48,6 +48,7 @@ gulp.task('dev', () => { }); app.use('/assets', express.static(path.resolve(__dirname, `${examples}/assets`))); + app.use('/modules', express.static('modules')); app.set('views', path.resolve(__dirname, `./${examples}`)); app.set('view engine', 'pug'); diff --git a/modules/.babelrc b/modules/.babelrc new file mode 100644 index 000000000..c2fb90b8d --- /dev/null +++ b/modules/.babelrc @@ -0,0 +1,11 @@ +{ + "presets": [ + "es2015" + ], + "plugins": [ + "add-module-exports", + "transform-decorators-legacy", + "transform-class-properties", + "transform-object-rest-spread" + ] +} diff --git a/modules/whs-module-audio/build/AudioModule.js b/modules/whs-module-audio/build/AudioModule.js new file mode 100644 index 000000000..281370180 --- /dev/null +++ b/modules/whs-module-audio/build/AudioModule.js @@ -0,0 +1,154 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(require("THREE")); + else if(typeof define === 'function' && define.amd) + define(["THREE"], factory); + else if(typeof exports === 'object') + exports["AudioModule"] = factory(require("THREE")); + else + root["AudioModule"] = factory(root["THREE"]); +})(this, function(__WEBPACK_EXTERNAL_MODULE_0__) { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; +/******/ +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // identity function for calling harmony imports with the correct context +/******/ __webpack_require__.i = function(value) { return value; }; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 1); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports) { + +module.exports = __WEBPACK_EXTERNAL_MODULE_0__; + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _three = __webpack_require__(0); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var PositionalAudioModule = function () { + function PositionalAudioModule() { + var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, PositionalAudioModule); + + this.bridge = { + mesh: function mesh(_mesh, self) { + _mesh.add(self.positionalAudio); + return _mesh; + } + }; + + this.params = Object.assign({ + loop: true + }, params); + + this.audioListener = new _three.AudioListener(); + this.audioLoader = new _three.AudioLoader(); + + this.positionalAudio = new _three.PositionalAudio(this.audioListener); + this.positionalAudio.setLoop(this.params.loop); + } + + _createClass(PositionalAudioModule, [{ + key: 'addListener', + value: function addListener(object) { + object.native.add(this.audioListener); + } + }, { + key: 'playAudio', + value: function playAudio(path) { + var sound = this.positionalAudio; + + this.audioLoader.load(path, function (buffer) { + sound.setBuffer(buffer); + sound.setRefDistance(50); + sound.play(); + }); + } + }]); + + return PositionalAudioModule; +}(); + +exports.default = PositionalAudioModule; +module.exports = exports['default']; + +/***/ }) +/******/ ]); +}); +//# sourceMappingURL=AudioModule.js.map \ No newline at end of file diff --git a/modules/whs-module-audio/build/AudioModule.js.map b/modules/whs-module-audio/build/AudioModule.js.map new file mode 100644 index 000000000..5bbf778d8 --- /dev/null +++ b/modules/whs-module-audio/build/AudioModule.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap ff0997ffeeea461f2beb","webpack:///external \"THREE\"","webpack:///./src/index.js"],"names":["PositionalAudioModule","params","bridge","mesh","self","add","positionalAudio","Object","assign","loop","audioListener","audioLoader","setLoop","object","native","path","sound","load","setBuffer","buffer","setRefDistance","play"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;ACVA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA,mDAA2C,cAAc;;AAEzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;AChEA,+C;;;;;;;;;;;;;;;;ACAA;;;;IAMqBA,qB;AACnB,mCAAyB;AAAA,QAAbC,MAAa,uEAAJ,EAAI;;AAAA;;AAAA,SA0BzBC,MA1ByB,GA0BhB;AACPC,UADO,gBACFA,KADE,EACIC,IADJ,EACU;AACfD,cAAKE,GAAL,CAASD,KAAKE,eAAd;AACA,eAAOH,KAAP;AACD;AAJM,KA1BgB;;AACvB,SAAKF,MAAL,GAAcM,OAAOC,MAAP,CAAc;AAC1BC,YAAM;AADoB,KAAd,EAEXR,MAFW,CAAd;;AAIA,SAAKS,aAAL,GAAqB,0BAArB;AACA,SAAKC,WAAL,GAAmB,wBAAnB;;AAEA,SAAKL,eAAL,GAAuB,2BAAoB,KAAKI,aAAzB,CAAvB;AACA,SAAKJ,eAAL,CAAqBM,OAArB,CAA6B,KAAKX,MAAL,CAAYQ,IAAzC;AACD;;;;gCAEWI,M,EAAQ;AAClBA,aAAOC,MAAP,CAAcT,GAAd,CAAkB,KAAKK,aAAvB;AACD;;;8BAESK,I,EAAM;AACd,UAAMC,QAAQ,KAAKV,eAAnB;;AAEA,WAAKK,WAAL,CAAiBM,IAAjB,CAAsBF,IAAtB,EAA4B,kBAAU;AACpCC,cAAME,SAAN,CAAgBC,MAAhB;AACAH,cAAMI,cAAN,CAAqB,EAArB;AACAJ,cAAMK,IAAN;AACD,OAJD;AAKD;;;;;;kBAzBkBrB,qB","file":"AudioModule.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"THREE\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"THREE\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"AudioModule\"] = factory(require(\"THREE\"));\n\telse\n\t\troot[\"AudioModule\"] = factory(root[\"THREE\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_0__) {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap ff0997ffeeea461f2beb","module.exports = __WEBPACK_EXTERNAL_MODULE_0__;\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"THREE\"\n// module id = 0\n// module chunks = 0","import {\n PositionalAudio,\n AudioListener,\n AudioLoader\n} from 'three';\n\nexport default class PositionalAudioModule {\n constructor(params = {}) {\n this.params = Object.assign({\n loop: true\n }, params);\n\n this.audioListener = new AudioListener();\n this.audioLoader = new AudioLoader();\n\n this.positionalAudio = new PositionalAudio(this.audioListener);\n this.positionalAudio.setLoop(this.params.loop);\n }\n\n addListener(object) {\n object.native.add(this.audioListener);\n };\n\n playAudio(path) {\n const sound = this.positionalAudio;\n\n this.audioLoader.load(path, buffer => {\n sound.setBuffer(buffer);\n sound.setRefDistance(50);\n sound.play();\n });\n };\n\n bridge = {\n mesh(mesh, self) {\n mesh.add(self.positionalAudio);\n return mesh;\n }\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/index.js"],"sourceRoot":""} \ No newline at end of file diff --git a/modules/whs-module-audio/package.json b/modules/whs-module-audio/package.json new file mode 100644 index 000000000..2b5c2e283 --- /dev/null +++ b/modules/whs-module-audio/package.json @@ -0,0 +1,17 @@ +{ + "name": "whs-module-audio", + "version": "0.0.1", + "description": "Audio module for whs", + "main": "build/AudioPlugin.js", + "scripts": { + "start": "webpack --watch", + "build": "webpack", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "whs-module", + "audio" + ], + "author": "hirako2000", + "license": "MIT" +} diff --git a/modules/whs-module-audio/src/index.js b/modules/whs-module-audio/src/index.js new file mode 100644 index 000000000..2eebabb06 --- /dev/null +++ b/modules/whs-module-audio/src/index.js @@ -0,0 +1,40 @@ +import { + PositionalAudio, + AudioListener, + AudioLoader +} from 'three'; + +export default class PositionalAudioModule { + constructor(params = {}) { + this.params = Object.assign({ + loop: true + }, params); + + this.audioListener = new AudioListener(); + this.audioLoader = new AudioLoader(); + + this.positionalAudio = new PositionalAudio(this.audioListener); + this.positionalAudio.setLoop(this.params.loop); + } + + addListener(object) { + object.native.add(this.audioListener); + }; + + playAudio(path) { + const sound = this.positionalAudio; + + this.audioLoader.load(path, buffer => { + sound.setBuffer(buffer); + sound.setRefDistance(50); + sound.play(); + }); + }; + + bridge = { + mesh(mesh, self) { + mesh.add(self.positionalAudio); + return mesh; + } + } +} diff --git a/modules/whs-module-audio/webpack.config.babel.js b/modules/whs-module-audio/webpack.config.babel.js new file mode 100644 index 000000000..dde448b99 --- /dev/null +++ b/modules/whs-module-audio/webpack.config.babel.js @@ -0,0 +1,45 @@ +import path from 'path'; +import webpack from 'webpack'; + +process.env.BABEL_ENV = 'browser'; + +const isProduction = process.env.NODE_ENV === 'production'; + +console.log( + isProduction + ? 'Production mode' + : 'Development mode' +); + +export default { + devtool: isProduction ? false : 'source-map', + entry: './src/index.js', + target: 'web', + output: { + path: path.join(__dirname, './build/'), + filename: 'AudioModule.js', + libraryTarget: 'umd', + library: 'AudioModule' + }, + externals: { + whs: 'WHS', + three: 'THREE' + }, + module: { + loaders: [ + { + test: /\.js$/, + exclude: /node_modules/, + loader: 'babel-loader' + } + ] + }, + plugins: isProduction + ? [ + new webpack.optimize.UglifyJsPlugin({ + compress: {warnings: false}, + minimize: true + }) + ] + : [] +};