mirror of
https://github.com/photonstorm/phaser
synced 2024-11-22 20:53:39 +00:00
Added first pass at Video Game Object
This commit is contained in:
parent
de1034091e
commit
9429f66adb
7 changed files with 1007 additions and 1 deletions
|
@ -39,6 +39,7 @@ var GameObjects = {
|
|||
Text: require('./text/static/Text'),
|
||||
TileSprite: require('./tilesprite/TileSprite'),
|
||||
Zone: require('./zone/Zone'),
|
||||
Video: require('./video/Video'),
|
||||
|
||||
// Shapes
|
||||
|
||||
|
@ -74,6 +75,7 @@ var GameObjects = {
|
|||
Text: require('./text/static/TextFactory'),
|
||||
TileSprite: require('./tilesprite/TileSpriteFactory'),
|
||||
Zone: require('./zone/ZoneFactory'),
|
||||
Video: require('./video/VideoFactory'),
|
||||
|
||||
// Shapes
|
||||
Arc: require('./shape/arc/ArcFactory'),
|
||||
|
@ -102,7 +104,8 @@ var GameObjects = {
|
|||
StaticBitmapText: require('./bitmaptext/static/BitmapTextCreator'),
|
||||
Text: require('./text/static/TextCreator'),
|
||||
TileSprite: require('./tilesprite/TileSpriteCreator'),
|
||||
Zone: require('./zone/ZoneCreator')
|
||||
Zone: require('./zone/ZoneCreator'),
|
||||
Video: require('./video/VideoCreator')
|
||||
}
|
||||
|
||||
};
|
||||
|
|
839
src/gameobjects/video/Video.js
Normal file
839
src/gameobjects/video/Video.js
Normal file
|
@ -0,0 +1,839 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2019 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Class = require('../../utils/Class');
|
||||
var Components = require('../components');
|
||||
var GameObject = require('../GameObject');
|
||||
var UUID = require('../../utils/string/UUID');
|
||||
var VideoRender = require('./VideoRender');
|
||||
|
||||
/**
|
||||
* @classdesc
|
||||
* A Video Game Object.
|
||||
*
|
||||
* @class Video
|
||||
* @extends Phaser.GameObjects.GameObject
|
||||
* @memberof Phaser.GameObjects
|
||||
* @constructor
|
||||
* @since 3.20.0
|
||||
*
|
||||
* @extends Phaser.GameObjects.Components.Alpha
|
||||
* @extends Phaser.GameObjects.Components.BlendMode
|
||||
* @extends Phaser.GameObjects.Components.Depth
|
||||
* @extends Phaser.GameObjects.Components.Flip
|
||||
* @extends Phaser.GameObjects.Components.GetBounds
|
||||
* @extends Phaser.GameObjects.Components.Mask
|
||||
* @extends Phaser.GameObjects.Components.Origin
|
||||
* @extends Phaser.GameObjects.Components.Pipeline
|
||||
* @extends Phaser.GameObjects.Components.ScrollFactor
|
||||
* @extends Phaser.GameObjects.Components.Size
|
||||
* @extends Phaser.GameObjects.Components.TextureCrop
|
||||
* @extends Phaser.GameObjects.Components.Tint
|
||||
* @extends Phaser.GameObjects.Components.Transform
|
||||
* @extends Phaser.GameObjects.Components.Visible
|
||||
*
|
||||
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
|
||||
* @param {number} x - The horizontal position of this Game Object in the world.
|
||||
* @param {number} y - The vertical position of this Game Object in the world.
|
||||
* @param {string} texture - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
|
||||
* @param {(string|integer)} [frame] - An optional frame from the Texture this Game Object is rendering with.
|
||||
*/
|
||||
var Video = new Class({
|
||||
|
||||
Extends: GameObject,
|
||||
|
||||
Mixins: [
|
||||
Components.Alpha,
|
||||
Components.BlendMode,
|
||||
Components.Depth,
|
||||
Components.Flip,
|
||||
Components.GetBounds,
|
||||
Components.Mask,
|
||||
Components.Origin,
|
||||
Components.Pipeline,
|
||||
Components.ScrollFactor,
|
||||
Components.Size,
|
||||
Components.TextureCrop,
|
||||
Components.Tint,
|
||||
Components.Transform,
|
||||
Components.Visible,
|
||||
VideoRender
|
||||
],
|
||||
|
||||
initialize:
|
||||
|
||||
function Video (scene, x, y, key)
|
||||
{
|
||||
GameObject.call(this, scene, 'Video');
|
||||
|
||||
var textureKey = UUID();
|
||||
|
||||
this.snapshot = scene.sys.textures.createCanvas(textureKey, 8, 8);
|
||||
|
||||
/**
|
||||
* @property {HTMLVideoElement} video - The HTML Video Element that is added to the document.
|
||||
*/
|
||||
this.video = null;
|
||||
this.videoTexture = null;
|
||||
this.videoTextureSource = null;
|
||||
|
||||
/**
|
||||
* @property {boolean} touchLocked - true if this video is currently locked awaiting a touch event. This happens on some mobile devices, such as iOS.
|
||||
* @default
|
||||
*/
|
||||
this.touchLocked = false;
|
||||
|
||||
/**
|
||||
* Start playing the video when it's unlocked.
|
||||
* @property {boolean} playWhenUnlocked
|
||||
* @default
|
||||
*/
|
||||
this.playWhenUnlocked = true;
|
||||
|
||||
/**
|
||||
* @property {integer} timeout - The amount of ms allowed to elapsed before the Video.onTimeout signal is dispatched while waiting for webcam access.
|
||||
* @default
|
||||
*/
|
||||
this.timeout = 15000;
|
||||
|
||||
/**
|
||||
* @property {integer} _timeOutID - setTimeout ID.
|
||||
* @private
|
||||
*/
|
||||
this._timeOutID = null;
|
||||
|
||||
/**
|
||||
* @property {MediaStream} videoStream - The Video Stream data. Only set if this Video is streaming from the webcam via `startMediaStream`.
|
||||
*/
|
||||
this.videoStream = null;
|
||||
|
||||
/**
|
||||
* @property {boolean} isStreaming - Is there a streaming video source? I.e. from a webcam.
|
||||
*/
|
||||
this.isStreaming = false;
|
||||
|
||||
/**
|
||||
* When starting playback of a video Phaser will monitor its readyState using a setTimeout call.
|
||||
* The setTimeout happens once every `Video.retryInterval` ms. It will carry on monitoring the video
|
||||
* state in this manner until the `retryLimit` is reached and then abort.
|
||||
* @property {integer} retryLimit
|
||||
* @default
|
||||
*/
|
||||
this.retryLimit = 20;
|
||||
|
||||
/**
|
||||
* @property {integer} retry - The current retry attempt.
|
||||
* @default
|
||||
*/
|
||||
this.retry = 0;
|
||||
|
||||
/**
|
||||
* @property {integer} retryInterval - The number of ms between each retry at monitoring the status of a downloading video.
|
||||
* @default
|
||||
*/
|
||||
this.retryInterval = 500;
|
||||
|
||||
/**
|
||||
* @property {integer} _retryID - The callback ID of the retry setTimeout.
|
||||
* @private
|
||||
*/
|
||||
this._retryID = null;
|
||||
|
||||
/**
|
||||
* @property {boolean} _codeMuted - Internal mute tracking var.
|
||||
* @private
|
||||
* @default
|
||||
*/
|
||||
this._codeMuted = false;
|
||||
|
||||
/**
|
||||
* @property {boolean} _muted - Internal mute tracking var.
|
||||
* @private
|
||||
* @default
|
||||
*/
|
||||
this._muted = false;
|
||||
|
||||
/**
|
||||
* @property {boolean} _codePaused - Internal paused tracking var.
|
||||
* @private
|
||||
* @default
|
||||
*/
|
||||
this._codePaused = false;
|
||||
|
||||
/**
|
||||
* @property {boolean} _paused - Internal paused tracking var.
|
||||
* @private
|
||||
* @default
|
||||
*/
|
||||
this._paused = false;
|
||||
|
||||
/**
|
||||
* @property {boolean} _pending - Internal var tracking play pending.
|
||||
* @private
|
||||
* @default
|
||||
*/
|
||||
this._pending = false;
|
||||
|
||||
/**
|
||||
* @property {boolean} _pendingChangeSource - Internal var tracking play pending.
|
||||
* @private
|
||||
* @default
|
||||
*/
|
||||
this._pendingChangeSource = false;
|
||||
|
||||
/**
|
||||
* @property {boolean} _autoplay - Internal var tracking autoplay when changing source.
|
||||
* @private
|
||||
* @default
|
||||
*/
|
||||
this._autoplay = false;
|
||||
|
||||
/**
|
||||
* @property {function} _endCallback - The addEventListener ended function.
|
||||
* @private
|
||||
*/
|
||||
this._endCallback = null;
|
||||
|
||||
/**
|
||||
* @property {function} _playCallback - The addEventListener playing function.
|
||||
* @private
|
||||
*/
|
||||
this._playCallback = null;
|
||||
|
||||
/**
|
||||
* The internal crop data object, as used by `setCrop` and passed to the `Frame.setCropUVs` method.
|
||||
*
|
||||
* @name Phaser.GameObjects.Image#_crop
|
||||
* @type {object}
|
||||
* @private
|
||||
* @since 3.11.0
|
||||
*/
|
||||
this._crop = this.resetCropObject();
|
||||
|
||||
// if (this.game.device.needsTouchUnlock())
|
||||
// {
|
||||
// this.setTouchLock();
|
||||
// }
|
||||
// else if (_video)
|
||||
// {
|
||||
// _video.locked = false;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
this.setTexture(textureKey);
|
||||
this.setPosition(x, y);
|
||||
this.setSizeToFrame();
|
||||
this.setOrigin(0.5, 0.5);
|
||||
this.initPipeline();
|
||||
|
||||
var ctx = this.texture.context;
|
||||
ctx.fillStyle = '#ff0000';
|
||||
ctx.fillRect(0, 0, 8, 8);
|
||||
|
||||
this.texture.refresh();
|
||||
},
|
||||
|
||||
/**
|
||||
* Starts this video playing.
|
||||
*
|
||||
* If the video is already playing, or has been queued to play with `changeSource` then this method just returns.
|
||||
*
|
||||
* @method Phaser.Video#play
|
||||
* @param {boolean} [loop=false] - Should the video loop automatically when it reaches the end? Please note that at present some browsers (i.e. Chrome) do not support *seamless* video looping.
|
||||
* @param {number} [playbackRate=1] - The playback rate of the video. 1 is normal speed, 2 is x2 speed, and so on. You cannot set a negative playback rate.
|
||||
* @return {Phaser.Video} This Video object for method chaining.
|
||||
*/
|
||||
play: function (loop, playbackRate)
|
||||
{
|
||||
if (loop === undefined) { loop = false; }
|
||||
if (playbackRate === undefined) { playbackRate = 1; }
|
||||
|
||||
if (this._pendingChangeSource)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
// if (this.game.sound.onMute)
|
||||
// {
|
||||
// this.game.sound.onMute.add(this.setMute, this);
|
||||
// this.game.sound.onUnMute.add(this.unsetMute, this);
|
||||
|
||||
// if (this.game.sound.mute)
|
||||
// {
|
||||
// this.setMute();
|
||||
// }
|
||||
// }
|
||||
|
||||
// this.game.onPause.add(this.setPause, this);
|
||||
// this.game.onResume.add(this.setResume, this);
|
||||
|
||||
this._endCallback = this.complete.bind(this);
|
||||
|
||||
this.video.addEventListener('ended', this._endCallback, true);
|
||||
this.video.addEventListener('webkitendfullscreen', this._endCallback, true);
|
||||
|
||||
if (loop)
|
||||
{
|
||||
this.video.loop = 'loop';
|
||||
}
|
||||
else
|
||||
{
|
||||
this.video.loop = '';
|
||||
}
|
||||
|
||||
this.video.playbackRate = playbackRate;
|
||||
|
||||
if (this.touchLocked)
|
||||
{
|
||||
this._pending = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._pending = false;
|
||||
|
||||
if (this.key !== null)
|
||||
{
|
||||
if (this.video.readyState !== 4)
|
||||
{
|
||||
this.retry = this.retryLimit;
|
||||
this._retryID = window.setTimeout(this.checkVideoProgress.bind(this), this.retryInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._playCallback = this.playHandler.bind(this);
|
||||
this.video.addEventListener('playing', this._playCallback, true);
|
||||
}
|
||||
}
|
||||
|
||||
this.video.play();
|
||||
|
||||
// this.onPlay.dispatch(this, loop, playbackRate);
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the video starts to play. Updates the texture.
|
||||
*
|
||||
* @method Phaser.Video#playHandler
|
||||
* @private
|
||||
*/
|
||||
playHandler: function ()
|
||||
{
|
||||
this.video.removeEventListener('playing', this._playCallback, true);
|
||||
|
||||
this.updateTexture();
|
||||
},
|
||||
|
||||
/**
|
||||
* Stops the video playing.
|
||||
*
|
||||
* This removes all locally set signals.
|
||||
*
|
||||
* If you only wish to pause playback of the video, to resume at a later time, use `Video.paused = true` instead.
|
||||
* If the video hasn't finished downloading calling `Video.stop` will not abort the download. To do that you need to
|
||||
* call `Video.destroy` instead.
|
||||
*
|
||||
* If you are using a video stream from a webcam then calling Stop will disconnect the MediaStream session and disable the webcam.
|
||||
*
|
||||
* @method Phaser.Video#stop
|
||||
* @return {Phaser.Video} This Video object for method chaining.
|
||||
*/
|
||||
stop: function ()
|
||||
{
|
||||
// if (this.game.sound.onMute)
|
||||
// {
|
||||
// this.game.sound.onMute.remove(this.setMute, this);
|
||||
// this.game.sound.onUnMute.remove(this.unsetMute, this);
|
||||
// }
|
||||
|
||||
// this.game.onPause.remove(this.setPause, this);
|
||||
// this.game.onResume.remove(this.setResume, this);
|
||||
|
||||
// Stream or file?
|
||||
|
||||
if (this.isStreaming)
|
||||
{
|
||||
if (this.video.mozSrcObject)
|
||||
{
|
||||
this.video.mozSrcObject.stop();
|
||||
this.video.src = null;
|
||||
}
|
||||
else if (this.video.srcObject)
|
||||
{
|
||||
this.video.srcObject.stop();
|
||||
this.video.src = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.video.src = '';
|
||||
|
||||
if (this.videoStream.active)
|
||||
{
|
||||
this.videoStream.active = false;
|
||||
}
|
||||
else
|
||||
if (this.videoStream.getTracks)
|
||||
{
|
||||
this.videoStream.getTracks().forEach(function (track)
|
||||
{
|
||||
track.stop();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.videoStream.stop();
|
||||
}
|
||||
}
|
||||
|
||||
this.videoStream = null;
|
||||
this.isStreaming = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.video.removeEventListener('ended', this._endCallback, true);
|
||||
this.video.removeEventListener('webkitendfullscreen', this._endCallback, true);
|
||||
this.video.removeEventListener('playing', this._playCallback, true);
|
||||
|
||||
if (this.touchLocked)
|
||||
{
|
||||
this._pending = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.video.pause();
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new Video element from the given URL.
|
||||
*
|
||||
* @method Phaser.Video#createVideoFromURL
|
||||
* @param {string} url - The URL of the video.
|
||||
* @param {boolean} [autoplay=false] - Automatically start the video?
|
||||
* @return {Phaser.Video} This Video object for method chaining.
|
||||
*/
|
||||
createVideoFromURL: function (url, autoplay)
|
||||
{
|
||||
if (autoplay === undefined) { autoplay = false; }
|
||||
|
||||
this.video = document.createElement('video');
|
||||
this.video.controls = false;
|
||||
|
||||
if (autoplay)
|
||||
{
|
||||
this.video.setAttribute('autoplay', 'autoplay');
|
||||
}
|
||||
|
||||
this.video.src = url;
|
||||
|
||||
this.video.canplay = true;
|
||||
|
||||
this.video.load();
|
||||
|
||||
this.retry = this.retryLimit;
|
||||
|
||||
this._retryID = window.setTimeout(this.checkVideoProgress.bind(this), this.retryInterval);
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Internal callback that monitors the download progress of a video after changing its source.
|
||||
*
|
||||
* @method Phaser.Video#checkVideoProgress
|
||||
* @private
|
||||
*/
|
||||
checkVideoProgress: function ()
|
||||
{
|
||||
if (this.video.readyState === 4)
|
||||
{
|
||||
this._pendingChangeSource = false;
|
||||
|
||||
// We've got enough data to update the texture for playback
|
||||
this.updateTexture();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.retry--;
|
||||
|
||||
if (this.retry > 0)
|
||||
{
|
||||
this._retryID = window.setTimeout(this.checkVideoProgress.bind(this), this.retryInterval);
|
||||
}
|
||||
else
|
||||
{
|
||||
console.warn('Phaser.Video: Unable to start downloading video in time', this.isStreaming);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called automatically if the video source changes and updates the internal texture dimensions.
|
||||
* Then dispatches the onChangeSource signal.
|
||||
*
|
||||
* @method Phaser.Video#updateTexture
|
||||
* @param {object} [event] - The event which triggered the texture update.
|
||||
* @param {integer} [width] - The new width of the video. If undefined `video.videoWidth` is used.
|
||||
* @param {integer} [height] - The new height of the video. If undefined `video.videoHeight` is used.
|
||||
*/
|
||||
updateTexture: function (event, width, height)
|
||||
{
|
||||
var newSize = false;
|
||||
|
||||
if (width === undefined || width === null) { width = this.video.videoWidth; newSize = true; }
|
||||
if (height === undefined || height === null) { height = this.video.videoHeight; }
|
||||
|
||||
// First we'll update our current CanvasTexture
|
||||
if (newSize)
|
||||
{
|
||||
this.texture.setSize(width, height);
|
||||
}
|
||||
|
||||
if (!this.videoTexture)
|
||||
{
|
||||
this.videoTexture = this.scene.sys.textures.create(UUID(), this.video, width, height);
|
||||
this.videoTextureSource = this.videoTexture.source[0];
|
||||
this.videoTexture.add('__BASE', 0, 0, 0, width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
var textureSource = this.videoTextureSource;
|
||||
|
||||
textureSource.source = this.video;
|
||||
textureSource.width = width;
|
||||
textureSource.height = height;
|
||||
}
|
||||
|
||||
// Swap out the canvas texture for the video texture
|
||||
// this.canvasTexture = this.texture;
|
||||
// this.canvasFrame = this.frame;
|
||||
|
||||
this.texture = this.videoTexture;
|
||||
this.frame = this.videoTexture.get();
|
||||
|
||||
this.setSizeToFrame();
|
||||
this.setOriginFromFrame();
|
||||
|
||||
if (this._autoplay)
|
||||
{
|
||||
this.video.play();
|
||||
}
|
||||
},
|
||||
|
||||
preUpdate: function ()
|
||||
{
|
||||
if (this.videoTextureSource && this.playing)
|
||||
{
|
||||
this.videoTextureSource.update();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @name Phaser.Video#currentTime
|
||||
* @property {number} currentTime - The current time of the video in seconds. If set the video will attempt to seek to that point in time.
|
||||
*/
|
||||
getCurrentTime: function ()
|
||||
{
|
||||
return (this.video) ? this.video.currentTime : 0;
|
||||
},
|
||||
|
||||
setCurrentTime: function (value)
|
||||
{
|
||||
if (this.video)
|
||||
{
|
||||
this.video.currentTime = value;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* @name Phaser.Video#duration
|
||||
* @property {number} duration - The duration of the video in seconds.
|
||||
* @readOnly
|
||||
*/
|
||||
getDuration: function ()
|
||||
{
|
||||
return (this.video) ? this.video.duration : 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* @name Phaser.Video#progress
|
||||
* @property {number} progress - The progress of this video. This is a value between 0 and 1, where 0 is the start and 1 is the end of the video.
|
||||
* @readOnly
|
||||
*/
|
||||
getProgress: function ()
|
||||
{
|
||||
return (this.video) ? (this.video.currentTime / this.video.duration) : 0;
|
||||
},
|
||||
|
||||
isMuted: function ()
|
||||
{
|
||||
return this._muted;
|
||||
},
|
||||
|
||||
setMute: function (value)
|
||||
{
|
||||
if (value === undefined) { value = true; }
|
||||
|
||||
if (value)
|
||||
{
|
||||
if (!this._muted)
|
||||
{
|
||||
this._muted = true;
|
||||
this._codeMuted = true;
|
||||
|
||||
if (this.video)
|
||||
{
|
||||
this.video.muted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// eslint-disable-next-line no-lonely-if
|
||||
if (this._muted)
|
||||
{
|
||||
this._muted = false;
|
||||
this._codeMuted = false;
|
||||
|
||||
if (this.video)
|
||||
{
|
||||
this.video.muted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
pause: function ()
|
||||
{
|
||||
if (this._paused || this.touchLocked)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
this._codePaused = true;
|
||||
this._paused = true;
|
||||
|
||||
if (this.video)
|
||||
{
|
||||
this.video.pause();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
resume: function ()
|
||||
{
|
||||
if (!this._paused || this._codePaused || this.touchLocked)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
this._codePaused = false;
|
||||
this._paused = false;
|
||||
|
||||
if (this.video && !this.video.ended)
|
||||
{
|
||||
this.video.play();
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
getVolume: function ()
|
||||
{
|
||||
return (this.video) ? this.video.volume : 1;
|
||||
},
|
||||
|
||||
/**
|
||||
* @name Phaser.Video#volume
|
||||
* @property {number} volume - Gets or sets the volume of the Video, a value between 0 and 1. The value given is clamped to the range 0 to 1.
|
||||
*/
|
||||
setVolume: function (value)
|
||||
{
|
||||
if (value === undefined) { value = 1; }
|
||||
|
||||
if (value < 0)
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
else if (value > 1)
|
||||
{
|
||||
value = 1;
|
||||
}
|
||||
|
||||
if (this.video)
|
||||
{
|
||||
this.video.volume = value;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
getPlaybackRate: function ()
|
||||
{
|
||||
return (this.video) ? this.video.playbackRate : 1;
|
||||
},
|
||||
|
||||
/**
|
||||
* @name Phaser.Video#playbackRate
|
||||
* @property {number} playbackRate - Gets or sets the playback rate of the Video. This is the speed at which the video is playing.
|
||||
*/
|
||||
setPlaybackRate: function (rate)
|
||||
{
|
||||
if (this.video)
|
||||
{
|
||||
this.video.playbackRate = rate;
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
getLoop: function ()
|
||||
{
|
||||
return (this.video) ? this.video.loop : false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets or sets if the Video is set to loop.
|
||||
* Please note that at present some browsers (i.e. Chrome) do not support *seamless* video looping.
|
||||
* If the video isn't yet set this will always return false.
|
||||
*
|
||||
* @name Phaser.Video#loop
|
||||
* @property {boolean} loop
|
||||
*/
|
||||
setLoop: function (value)
|
||||
{
|
||||
if (value === undefined) { value = true; }
|
||||
|
||||
if (this.video)
|
||||
{
|
||||
this.video.loop = (value) ? 'loop' : '';
|
||||
}
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* @name Phaser.Video#playing
|
||||
* @property {boolean} playing - True if the video is currently playing (and not paused or ended), otherwise false.
|
||||
* @readOnly
|
||||
*/
|
||||
isPlaying: function ()
|
||||
{
|
||||
return (this.video) ? !(this.video.paused && this.video.ended) : false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Grabs the current frame from the Video or Video Stream and renders it to the Video.snapshot BitmapData.
|
||||
*
|
||||
* You can optionally set if the BitmapData should be cleared or not, the alpha and the blend mode of the draw.
|
||||
*
|
||||
* If you need more advanced control over the grabbing them call `Video.snapshot.copy` directly with the same parameters as BitmapData.copy.
|
||||
*
|
||||
* @method Phaser.Video#grab
|
||||
* @param {boolean} [clear=false] - Should the BitmapData be cleared before the Video is grabbed? Unless you are using alpha or a blend mode you can usually leave this set to false.
|
||||
* @param {number} [alpha=1] - The alpha that will be set on the video before drawing. A value between 0 (fully transparent) and 1, opaque.
|
||||
* @param {string} [blendMode=null] - The composite blend mode that will be used when drawing. The default is no blend mode at all. This is a Canvas globalCompositeOperation value such as 'lighter' or 'xor'.
|
||||
* @return {Phaser.BitmapData} A reference to the Video.snapshot BitmapData object for further method chaining.
|
||||
*/
|
||||
grab: function (clear, alpha, blendMode)
|
||||
{
|
||||
if (clear === undefined) { clear = false; }
|
||||
if (alpha === undefined) { alpha = 1; }
|
||||
if (blendMode === undefined) { blendMode = null; }
|
||||
|
||||
if (clear)
|
||||
{
|
||||
this.snapshot.clear();
|
||||
}
|
||||
|
||||
// Set globalAlpha
|
||||
// Set blendMode
|
||||
|
||||
this.snapshot.draw(0, 0, this.video);
|
||||
|
||||
return this.snapshot;
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the Video element from the DOM by calling parentNode.removeChild on itself.
|
||||
* Also removes the autoplay and src attributes and nulls the reference.
|
||||
*
|
||||
* @method Phaser.Video#removeVideoElement
|
||||
*/
|
||||
removeVideoElement: function ()
|
||||
{
|
||||
if (!this.video)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.video.parentNode)
|
||||
{
|
||||
this.video.parentNode.removeChild(this.video);
|
||||
}
|
||||
|
||||
while (this.video.hasChildNodes())
|
||||
{
|
||||
this.video.removeChild(this.video.firstChild);
|
||||
}
|
||||
|
||||
this.video.removeAttribute('autoplay');
|
||||
this.video.removeAttribute('src');
|
||||
|
||||
this.video = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys the Video object. This calls `Video.stop` and then `Video.removeVideoElement`.
|
||||
* If any Sprites are using this Video as their texture it is up to you to manage those.
|
||||
*
|
||||
* @method Phaser.Video#destroy
|
||||
*/
|
||||
destroy: function ()
|
||||
{
|
||||
this.stop();
|
||||
|
||||
this.removeVideoElement();
|
||||
|
||||
// if (this.touchLocked)
|
||||
// {
|
||||
// this.game.input.removeTouchLockCallback(this.unlock, this);
|
||||
// }
|
||||
|
||||
if (this._retryID)
|
||||
{
|
||||
window.clearTimeout(this._retryID);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @name Phaser.Video#playing
|
||||
* @property {boolean} playing - True if the video is currently playing (and not paused or ended), otherwise false.
|
||||
* @readOnly
|
||||
*/
|
||||
playing: {
|
||||
|
||||
get: function ()
|
||||
{
|
||||
return (this.video) ? !(this.video.paused && this.video.ended) : false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = Video;
|
27
src/gameobjects/video/VideoCanvasRenderer.js
Normal file
27
src/gameobjects/video/VideoCanvasRenderer.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2019 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders this Game Object with the Canvas Renderer to the given Camera.
|
||||
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
||||
* This method should not be called directly. It is a utility function of the Render module.
|
||||
*
|
||||
* @method Phaser.GameObjects.Image#renderCanvas
|
||||
* @since 3.0.0
|
||||
* @private
|
||||
*
|
||||
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
|
||||
* @param {Phaser.GameObjects.Image} src - The Game Object being rendered in this call.
|
||||
* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
|
||||
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
||||
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
||||
*/
|
||||
var VideoCanvasRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
|
||||
{
|
||||
renderer.batchSprite(src, src.frame, camera, parentMatrix);
|
||||
};
|
||||
|
||||
module.exports = VideoCanvasRenderer;
|
44
src/gameobjects/video/VideoCreator.js
Normal file
44
src/gameobjects/video/VideoCreator.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2019 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var BuildGameObject = require('../BuildGameObject');
|
||||
var GameObjectCreator = require('../GameObjectCreator');
|
||||
var GetAdvancedValue = require('../../utils/object/GetAdvancedValue');
|
||||
var Video = require('./Video');
|
||||
|
||||
/**
|
||||
* Creates a new Image Game Object and returns it.
|
||||
*
|
||||
* Note: This method will only be available if the Image Game Object has been built into Phaser.
|
||||
*
|
||||
* @method Phaser.GameObjects.GameObjectCreator#image
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param {object} config - The configuration object this Game Object will use to create itself.
|
||||
* @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object.
|
||||
*
|
||||
* @return {Phaser.GameObjects.Image} The Game Object that was created.
|
||||
*/
|
||||
GameObjectCreator.register('video', function (config, addToScene)
|
||||
{
|
||||
if (config === undefined) { config = {}; }
|
||||
|
||||
var key = GetAdvancedValue(config, 'key', null);
|
||||
var frame = GetAdvancedValue(config, 'frame', null);
|
||||
|
||||
var image = new Video(this.scene, 0, 0, key, frame);
|
||||
|
||||
if (addToScene !== undefined)
|
||||
{
|
||||
config.add = addToScene;
|
||||
}
|
||||
|
||||
BuildGameObject(this.scene, image, config);
|
||||
|
||||
return image;
|
||||
});
|
||||
|
||||
// When registering a factory function 'this' refers to the GameObjectCreator context.
|
41
src/gameobjects/video/VideoFactory.js
Normal file
41
src/gameobjects/video/VideoFactory.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2019 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var Video = require('./Video');
|
||||
var GameObjectFactory = require('../GameObjectFactory');
|
||||
|
||||
/**
|
||||
* Creates a new Image Game Object and adds it to the Scene.
|
||||
*
|
||||
* Note: This method will only be available if the Image Game Object has been built into Phaser.
|
||||
*
|
||||
* @method Phaser.GameObjects.GameObjectFactory#video
|
||||
* @since 3.20.0
|
||||
*
|
||||
* @param {number} x - The horizontal position of this Game Object in the world.
|
||||
* @param {number} y - The vertical position of this Game Object in the world.
|
||||
* @param {string} texture - The key of the Texture this Game Object will use to render with, as stored in the Texture Manager.
|
||||
* @param {(string|integer)} [frame] - An optional frame from the Texture this Game Object is rendering with.
|
||||
*
|
||||
* @return {Phaser.GameObjects.Image} The Game Object that was created.
|
||||
*/
|
||||
GameObjectFactory.register('video', function (x, y, videoURL)
|
||||
{
|
||||
var video = new Video(this.scene, x, y, videoURL);
|
||||
|
||||
this.displayList.add(video);
|
||||
this.updateList.add(video);
|
||||
|
||||
return video;
|
||||
});
|
||||
|
||||
// When registering a factory function 'this' refers to the GameObjectFactory context.
|
||||
//
|
||||
// There are several properties available to use:
|
||||
//
|
||||
// this.scene - a reference to the Scene that owns the GameObjectFactory
|
||||
// this.displayList - a reference to the Display List the Scene owns
|
||||
// this.updateList - a reference to the Update List the Scene owns
|
25
src/gameobjects/video/VideoRender.js
Normal file
25
src/gameobjects/video/VideoRender.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2019 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
var renderWebGL = require('../../utils/NOOP');
|
||||
var renderCanvas = require('../../utils/NOOP');
|
||||
|
||||
if (typeof WEBGL_RENDERER)
|
||||
{
|
||||
renderWebGL = require('./VideoWebGLRenderer');
|
||||
}
|
||||
|
||||
if (typeof CANVAS_RENDERER)
|
||||
{
|
||||
renderCanvas = require('./VideoCanvasRenderer');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
renderWebGL: renderWebGL,
|
||||
renderCanvas: renderCanvas
|
||||
|
||||
};
|
27
src/gameobjects/video/VideoWebGLRenderer.js
Normal file
27
src/gameobjects/video/VideoWebGLRenderer.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
/**
|
||||
* @author Richard Davey <rich@photonstorm.com>
|
||||
* @copyright 2019 Photon Storm Ltd.
|
||||
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Renders this Game Object with the WebGL Renderer to the given Camera.
|
||||
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
||||
* This method should not be called directly. It is a utility function of the Render module.
|
||||
*
|
||||
* @method Phaser.GameObjects.Image#renderWebGL
|
||||
* @since 3.0.0
|
||||
* @private
|
||||
*
|
||||
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
|
||||
* @param {Phaser.GameObjects.Image} src - The Game Object being rendered in this call.
|
||||
* @param {number} interpolationPercentage - Reserved for future use and custom pipelines.
|
||||
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
||||
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
||||
*/
|
||||
var VideoWebGLRenderer = function (renderer, src, interpolationPercentage, camera, parentMatrix)
|
||||
{
|
||||
this.pipeline.batchSprite(src, camera, parentMatrix);
|
||||
};
|
||||
|
||||
module.exports = VideoWebGLRenderer;
|
Loading…
Reference in a new issue