Skip to content

Commit

Permalink
Merge pull request #151 from playcanvas/master
Browse files Browse the repository at this point in the history
m
  • Loading branch information
guycalledfrank committed Jan 13, 2016
2 parents 2dc0ffc + a8eacc8 commit e59cdad
Show file tree
Hide file tree
Showing 16 changed files with 234 additions and 142 deletions.
1 change: 1 addition & 0 deletions build/dependencies.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
../src/framework/components/script/system.js
../src/framework/components/script/component.js
../src/framework/components/script/data.js
../src/framework/components/audio-source/constants.js
../src/framework/components/audio-source/system.js
../src/framework/components/audio-source/component.js
../src/framework/components/audio-source/data.js
Expand Down
24 changes: 4 additions & 20 deletions src/audio/audio-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,26 +80,6 @@ pc.extend(pc, function () {
AudioManager.isSupported = isSupported;

AudioManager.prototype = {
/**
* @private
* @function
* @name pc.AudioManager#createSound
* @description Load audio data from the url provided and create a pc.Sound object. Pass this to the success callback when complete
* or use the error callback if something goes wrong.
* @param {String} url The url of audio file to load, supported filetypes are mp3, ogg, wav.
* @param {Function} success Callback used when pc.Sound is successfully created from the loaded audio data. The callback is passed the new pc.Sound object.
* @param {Function} error Callback used if an error occurs.
*/
createSound: function (url, success, error) {
var sound = null;
if (pc.Sound) {
sound = new pc.Sound(this, url, success, error);
} else {
error();
}
return sound;
},


/**
* @private
Expand Down Expand Up @@ -153,6 +133,10 @@ pc.extend(pc, function () {
if (options.rollOffFactor) {
channel.setRollOffFactor(options.rollOffFactor);
}
if (options.distanceModel) {
channel.setDistanceModel(options.distanceModel);
}

channel.play();
}

Expand Down
2 changes: 1 addition & 1 deletion src/audio/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ pc.extend(pc, function () {
this.startTime = this.manager.context.currentTime;
this.source.start(0, this.startOffset % this.source.buffer.duration);

// Initialize volume and loop
// Initialize parameters
this.setVolume(this.volume);
this.setLoop(this.loop);
this.setPitch(this.pitch);
Expand Down
43 changes: 31 additions & 12 deletions src/audio/channel3d.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ pc.extend(pc, function () {
this.panner.rolloffFactor = factor;
},

getDistanceModel: function () {
return this.pannel.distanceModel;
},

setDistanceModel: function (distanceModel) {
this.panner.distanceModel = distanceModel;
},

/**
* @private
* @function
Expand All @@ -85,27 +93,29 @@ pc.extend(pc, function () {
} else if (pc.AudioManager.hasAudio()) {
// temp vector storage
var offset = new pc.Vec3();
var distance;

// Fall off function which should be the same as the one in the Web Audio API,
// taken from OpenAL
var fallOff = function (posOne, posTwo, refDistance, maxDistance, rolloffFactor) {
var min = 0;

// Fall off function which should be the same as the one in the Web Audio API
// Taken from https://developer.mozilla.org/en-US/docs/Web/API/PannerNode/distanceModel
var fallOff = function (posOne, posTwo, refDistance, maxDistance, rolloffFactor, distanceModel) {
offset = offset.sub2(posOne, posTwo);
distance = offset.length();
var distance = offset.length();

if (distance < refDistance) {
return 1;
} else if (distance > maxDistance) {
return 0;
} else {
var numerator = refDistance + (rolloffFactor * (distance - refDistance));
if ( numerator !== 0 ) {
return refDistance / numerator;
} else {
return 1;
var result = 0;
if (distanceModel === pc.DISTANCE_LINEAR) {
result = 1 - rolloffFactor * (distance - refDistance) / (maxDistance - refDistance);
} else if (distanceModel === pc.DISTANCE_INVERSE) {
result = refDistance / (refDistance + rolloffFactor * (distance - refDistance));
} else if (distanceModel === pc.DISTANCE_EXPONENTIAL) {
result = Math.pow(distance / refDistance, -rolloffFactor);
}

return pc.math.clamp(result, 0, 1);
}
};

Expand All @@ -116,6 +126,7 @@ pc.extend(pc, function () {
this.maxDistance = MAX_DISTANCE;
this.minDistance = 1;
this.rollOffFactor = 1;
this.distanceModel = pc.DISTANCE_INVERSE;

};
Channel3d = pc.inherits(Channel3d, pc.Channel);
Expand All @@ -133,7 +144,7 @@ pc.extend(pc, function () {

var lpos = listener.getPosition();

var factor = fallOff(lpos, this.position, this.minDistance, this.maxDistance, this.rollOffFactor);
var factor = fallOff(lpos, this.position, this.minDistance, this.maxDistance, this.rollOffFactor, this.distanceModel);

var v = this.getVolume();
this.source.volume = v * factor;
Expand Down Expand Up @@ -170,6 +181,14 @@ pc.extend(pc, function () {

setRollOffFactor: function (factor) {
this.rolloffFactor = factor;
},

getDistanceModel: function () {
return this.distanceModel;
},

setDistanceModel: function (distanceModel) {
this.distanceModel = distanceModel;
}
});
} else {
Expand Down
96 changes: 6 additions & 90 deletions src/audio/sound.js
Original file line number Diff line number Diff line change
@@ -1,100 +1,16 @@
pc.extend(pc, function () {
'use strict';

var Sound;

// checks if user is running IE
var ie = function () {
var ua = window.navigator.userAgent;

var msie = ua.indexOf('MSIE ');
if (msie > 0) {
// IE 10 or older => return version number
return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
}

var trident = ua.indexOf('Trident/');
if (trident > 0) {
// IE 11 => return version number
var rv = ua.indexOf('rv:');
return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
var Sound = function (resource) {
if (resource instanceof Audio) {
this.audio = resource;
} else {
this.buffer = resource;
}

return false;
this.isLoaded = !!(this.audio || this.buffer);
};

if (pc.AudioManager.hasAudioContext()) {
Sound = function (manager, url, success, error) {
this.buffer = null;
this.isLoaded = false;

if (!pc.AudioManager.isSupported(url, this.audio)) {
setTimeout(function () {
console.warn(pc.string.format('Audio format for {0} not supported', url));
success(this);
}, 0);
} else {
if (manager.context) {
pc.net.http.get(url, function (response) {
manager.context.decodeAudioData(response, function (buffer) {
this.buffer = buffer;
this.isLoaded = true;
success(this);
}.bind(this), error);
}.bind(this), {
error: error,
withCredentials: false
});
}
}
};
} else if (pc.AudioManager.hasAudio()) {
Sound = function (manager, url, success, error) {
this.isLoaded = false;
try {
this.audio = new Audio();
} catch (e) {
// Some windows platforms will report Audio as available, then throw an exception when
// the object is created.
console.warn(pc.string.format("No support for Audio element"));
success(this);
return;
}


if (!pc.AudioManager.isSupported(url, this.audio)) {
console.warn(pc.string.format('Audio format for {0} not supported', url));
success(this);
} else {
var isIE = ie();
// audio needs to be added to the DOM for IE
if (isIE)
document.body.appendChild(this.audio);

this.audio.oncanplaythrough = function () {
// remove from DOM no longer necessary
if (isIE)
document.body.removeChild(this.audio);

if (!this.isLoaded) {
this.isLoaded = true;
success(this);
}
}.bind(this);

this.audio.onerror = function () {
// remove from DOM no longer necessary
if (isIE)
document.body.removeChild(this.audio);

// continue loading through error
success(this);
};
this.audio.src = url;
}
};
}

return {
Sound: Sound
};
Expand Down
10 changes: 10 additions & 0 deletions src/framework/components/audio-source/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pc.extend(pc, function () {
* @property {Number} pitch The pitch modifier to play the audio with. Must be larger than 0.01
* @property {Boolean} loop If true the audio will restart when it finishes playing
* @property {Boolean} 3d If true the audio will play back at the location of the Entity in space, so the audio will be affect by the position of the {@link pc.AudioListenerComponent}
* @property {String} distanceModel Determines which algorithm to use to reduce the volume of the audio as it moves away from the listener. Can be one of 'linear', 'inverse' or 'exponential'. Default is 'inverse'.
* @property {Number} minDistance The minimum distance from the listener at which audio falloff begins.
* @property {Number} maxDistance The maximum distance from the listener at which audio falloff stops. Note the volume of the audio is not 0 after this distance, but just doesn't fall off anymore
* @property {Number} rollOffFactor The factor used in the falloff equation.
Expand All @@ -26,6 +27,7 @@ pc.extend(pc, function () {
this.on("set_minDistance", this.onSetMinDistance, this);
this.on("set_maxDistance", this.onSetMaxDistance, this);
this.on("set_rollOffFactor", this.onSetRollOffFactor, this);
this.on("set_distanceModel", this.onSetDistanceModel, this);
this.on("set_3d", this.onSet3d, this);
};
AudioSourceComponent = pc.inherits(AudioSourceComponent, pc.Component);
Expand Down Expand Up @@ -220,6 +222,14 @@ pc.extend(pc, function () {
}
},

onSetDistanceModel: function (name, oldValue, newValue) {
if (oldValue !== newValue) {
if (this.channel instanceof pc.Channel3d) {
this.channel.setDistanceModel(newValue);
}
}
},

onSet3d: function (name, oldValue, newValue) {
if (oldValue !== newValue) {
if (this.system.initialized && this.currentSource) {
Expand Down
6 changes: 6 additions & 0 deletions src/framework/components/audio-source/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pc.extend(pc, {
// distance model
DISTANCE_LINEAR: 'linear',
DISTANCE_INVERSE: 'inverse',
DISTANCE_EXPONENTIAL: 'exponential'
});
3 changes: 2 additions & 1 deletion src/framework/components/audio-source/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ pc.AudioSourceComponentData = function AudioSourceComponentData() {
this.minDistance = 1;
this.maxDistance = 10000;
this.rollOffFactor = 1;

this.distanceModel = pc.DISTANCE_INVERSE;

// not serialized
this.paused = true;

Expand Down
3 changes: 2 additions & 1 deletion src/framework/components/audio-source/system.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pc.extend(pc, function () {
'minDistance',
'maxDistance',
'rollOffFactor',
'distanceModel',
'sources',
'currentSource',
'channel'
Expand All @@ -43,7 +44,7 @@ pc.extend(pc, function () {

pc.extend(AudioSourceComponentSystem.prototype, {
initializeComponentData: function (component, data, properties) {
properties = ['activate', 'volume', 'pitch', 'loop', '3d', 'minDistance', 'maxDistance', 'rollOffFactor', 'enabled', 'assets'];
properties = ['activate', 'volume', 'pitch', 'loop', '3d', 'minDistance', 'maxDistance', 'rollOffFactor', 'distanceModel', 'enabled', 'assets'];
AudioSourceComponentSystem._super.initializeComponentData.call(this, component, data, properties);

component.paused = !(component.enabled && component.activate);
Expand Down
8 changes: 8 additions & 0 deletions src/framework/components/camera/post-effect-queue.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,14 @@ pc.extend(pc, function () {
},

_onCanvasResized: function (width, height) {

var rect = this.camera.rect;
var device = this.app.graphicsDevice;
var aspect = (device.width * rect.z) / (device.height * rect.w);
if (aspect !== this.camera.camera.getAspectRatio()) {
this.camera.camera.setAspectRatio(aspect);
}

// avoid resizing the render targets too often by using a timeout
if (this.resizeTimeout) {
clearTimeout(this.resizeTimeout);
Expand Down
10 changes: 10 additions & 0 deletions src/framework/components/collision/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ pc.extend(pc, function () {
this.on('set_height', this.onSetHeight, this);
this.on('set_axis', this.onSetAxis, this);
this.on("set_asset", this.onSetAsset, this);
this.on("set_model", this.onSetModel, this);
};
CollisionComponent = pc.inherits(CollisionComponent, pc.Component);

Expand Down Expand Up @@ -176,6 +177,15 @@ pc.extend(pc, function () {
}
},

onSetModel: function (name, oldValue, newValue) {
if (this.data.initialized && this.data.type === 'mesh') {
// recreate physical shapes skipping loading the model
// from the 'asset' as the model passed in newValue might
// have been created procedurally
this.system.implementations.mesh.doRecreatePhysicalShape(this);
}
},

onAssetRemoved: function (asset) {
asset.off('remove', this.onAssetRemoved, this);
if (this.data.asset === asset.id) {
Expand Down
8 changes: 8 additions & 0 deletions src/graphics/device.js
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,15 @@ pc.extend(pc, function () {
// Unset the render target
var target = this.renderTarget;
if (target) {
// Switch rendering back to the back buffer
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

// If the active render target is auto-mipmapped, generate its mip chain
var colorBuffer = target._colorBuffer;
if (colorBuffer._glTextureId && colorBuffer.autoMipmap && pc.math.powerOfTwo(colorBuffer._width) && pc.math.powerOfTwo(colorBuffer._height)) {
gl.bindTexture(colorBuffer._glTarget, colorBuffer._glTextureId);
gl.generateMipmap(colorBuffer._glTarget);
}
}
},

Expand Down
8 changes: 4 additions & 4 deletions src/polyfill/string.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
if (! String.prototype.startsWith) {
Object.defineProperty(String.prototype, 'startsWith', {
enumerable: false,
configurable: false,
writable: false,
configurable: true,
writable: true,
value: function(str) {
var that = this;
for(var i = 0, ceil = str.length; i < ceil; i++)
Expand All @@ -17,8 +17,8 @@ if (! String.prototype.startsWith) {
if (! String.prototype.endsWith) {
Object.defineProperty(String.prototype, 'endsWith', {
enumerable: false,
configurable: false,
writable: false,
configurable: true,
writable: true,
value: function(str) {
var that = this;
for(var i = 0, ceil = str.length; i < ceil; i++)
Expand Down
Loading

0 comments on commit e59cdad

Please sign in to comment.