//============================================================================= // MovieManager.js // ---------------------------------------------------------------------------- // (C)2015 Triacontane // This software is released under the MIT License. // http://opensource.org/licenses/mit-license.php // ---------------------------------------------------------------------------- // Version // 1.0.5 2021/01/26 autoplayをtrueに設定 // 1.0.4 2018/03/28 ムービー再生後、ロード完了前にムービーを停止するとムービーが停止されない問題を修正 // 1.0.3 2018/03/27 Saba_SimpleScenario.jsとの競合を解消(こちらの設定で上書き) // 1.0.2 2018/01/30 ヘルプの記述を修正 // 1.0.1 2016/06/24 メニューを開いたときに最後に表示していたムービーが写り込む不具合を修正 // 1.0.0 2016/06/09 初版 // ---------------------------------------------------------------------------- // [Blog] : https://triacontane.blogspot.jp/ // [Twitter]: https://twitter.com/triacontane/ // [GitHub] : https://github.com/triacontane/ //============================================================================= /*: * @plugindesc 動画管理プラグイン * @author トリアコンタン * * @help イベントコマンド「ムービーの再生」で再生できる動画をピクチャのように * コントロールできるようになります。 * 座標や拡大率はもちろん、ループ可否や再生速度を自由に調整可能です。 * イベントコマンド「ムービーの再生」後に以下のプラグインコマンドを実行します。 * (大抵のコマンドは「ムービーの再生」前でも機能しますが「MM_ウェイト」のみ *  「ムービーの再生」前では機能しません) * * プラグインコマンド詳細 * イベントコマンド「プラグインコマンド」から実行。 * (パラメータの間は半角スペースで区切る) * * すべてのプラグインコマンドはムービーが再生中でなくても有効です。 * * MM_移動_座標 [X座標] [Y座標] [移動時間(f)] [待ちフラグ(ON/OFF)] * ムービーの表示座標を時間を掛けて変更します。 * 下記の例は、座標[100:100]に[60]フレーム掛けて移動し、処理中はウェイトします。 * ex:MM_移動_座標 100 100 60 ON * * MM_移動_拡大率 [X拡大率(100%)] [Y拡大率(100%)] [時間(f)] [待ちフラグ(ON/OFF)] * ムービーの拡大率を時間を掛けて変更します。 * 下記の例は、縦横の拡大率を[50%]に60フレーム掛けて縮小し、 * 処理中はウェイトしません。 * ex:MM_移動_拡大率 50 50 60 * * MM_移動_不透明度 [不透明度(0-256)] [時間(f)] [ウェイトフラグ(ON/OFF)] * ムービーの不透明度を時間を掛けて変更します。 * 下記の例は、不透明度が変数[1]の値に即座に変更されます。 * ex:MM_移動_不透明度 \v[1] 0 ON * * MM_設定_再生速度 [再生速度(標準:1.0)] * ムービーの再生速度倍率を変更します。 * 下記の例は、再生速度が1.5倍になります。 * ex:MM_設定_再生速度 1.5 * * MM_設定_再生位置 [再生位置(S)] * ムービーの再生位置を変更します。 * ただしChromeの場合ロードしていない位置に移動すると再生が終了してしまうため * 使用には注意が必要です。(2016/06/12時点での最新版で確認) * 下記の例は、100秒目の再生位置にジャンプします。 * ex:MM_設定_再生位置 100 * * MM_設定_画面に合わせる [設定値(ON/OFF)] * ONにすると拡大率が100%の状態でムービーのサイズが画面にフィットするように * 調整されます。OFFにすると元の動画ファイルのサイズに合わせます。 * ex:MM_設定_画面に合わせる ON * * MM_設定_ループ [設定値(ON/OFF)] * ONにすると、再生終了後に最初からループ再生します。 * ex:MM_設定_ループ ON * * MM_一時停止 * 再生を一時停止します。 * ex:MM_一時停止 * * MM_再生 * 一時停止した状態から再生します。初回はイベントコマンドだけで再生されるので * このコマンドの実行は不要です。 * ex:MM_再生 * * MM_停止 * 再生を終了してムービーを消去します。 * ex:MM_停止 * * MM_ウェイト * ムービーの再生が終了するまでイベント実行を待機します。 * ループ再生している場合はゲームの進行が停止するので注意してください。 * このコマンドはイベント「ムービーの再生」の直後に実行してください。 * ex:MM_ウェイト * * スクリプトコマンド詳細 * * MovieManager.isPlaying(); * ムービーが再生中の場合にtrueを返します。 * * 制約事項 * 現状、ムービーの表示状態はセーブできません。 * * 利用規約: * 作者に無断で改変、再配布が可能で、利用形態(商用、18禁利用等) * についても制限はありません。 * このプラグインはもうあなたのものです。 */ /** * 動画管理モジュールです。 * @constructor */ function MovieManager() { throw new Error('This is a static class'); } (function() { 'use strict'; var metaTagPrefix = 'MM_'; var getCommandName = function(command) { return (command || '').toUpperCase(); }; var getArgFloat = function(arg, min, max) { if (arguments.length < 2) min = -Infinity; if (arguments.length < 3) max = Infinity; return (parseFloat(convertEscapeCharactersAndEval(arg, true)) || 0).clamp(min, max); }; var getArgNumber = function(arg, min, max) { if (arguments.length < 2) min = -Infinity; if (arguments.length < 3) max = Infinity; return (parseInt(convertEscapeCharactersAndEval(arg, true), 10) || 0).clamp(min, max); }; var getArgBoolean = function(arg) { return (arg || '').toUpperCase() === 'ON'; }; var convertEscapeCharactersAndEval = function(text, evalFlg) { if (text === null || text === undefined) { text = evalFlg ? '0' : ''; } var windowLayer = SceneManager._scene._windowLayer; if (windowLayer) { var result = windowLayer.children[0].convertEscapeCharacters(text); return evalFlg ? eval(result) : result; } else { return text; } }; //============================================================================= // Bitmap // キャプチャに表示中のムービーを含めます。 //============================================================================= var _Bitmap_snap = Bitmap.snap; Bitmap.snap = function(stage) { var bitmap = _Bitmap_snap.apply(this, arguments); if (Graphics.isVideoPlaying()) { var video = Graphics.getVideo(); bitmap.context.drawImage(video, video.x, video.y, video.width, video.height); } return bitmap; }; //============================================================================= // Graphics // ムービー再生に必要なタグを動的に生成します。 //============================================================================= Graphics._videoScaleFitScreen = false; Graphics._createVideo = function() { this._videoFrame = document.createElement('div'); this._videoFrame.id = 'GameVideoFrame'; this._video = document.createElement('video'); this._video.id = 'GameVideo'; this._videoVisible = false; document.body.appendChild(this._videoFrame); this._videoFrame.appendChild(this._video); this.setVideoContentsPosition(0, 0); this.setVideoContentsScale(1.0, 1.0); this._updateVideo(); this._centerElement(this._video); this._video.style.margin = 0; this._video.autoplay = true; this._videoLoading = false; }; Graphics.getVideo = function() { return this._video; }; var _Graphics_playVideo = Graphics.playVideo; Graphics.playVideo = function(src) { _Graphics_playVideo.apply(this, arguments); this._videoLoading = true; }; Graphics.stopVideo = function() { if (!this._isVideoVisible() && this.isVideoLoading()) { this._needVideoStop = true; } this._video.pause(); this._updateVisibility(false); }; Graphics.setVisibleMovie = function(value) { this._videoFrame.style.visibility = (value ? 'visible' : 'hidden'); }; Graphics.setVideoScaleFitScreen = function(value) { this._videoScaleFitScreen = value; this.setVideoContentsScale(this._video.scaleX, this._video.scaleY); }; var _Graphics_isVideoPlaying = Graphics.isVideoPlaying; Graphics.isVideoPlaying = function() { return _Graphics_isVideoPlaying.apply(this, arguments) || this.isVideoLoading(); }; Graphics.isVideoLoading = function() { return this._videoLoading; }; Graphics._updateVisibility = function(videoVisible) { this._videoVisible = videoVisible; this._video.style.visibility = (videoVisible ? 'visible' : 'hidden'); this._videoLoading = false; }; Graphics._isVideoVisible = function() { return this._videoVisible; }; var _Graphics__onVideoLoad = Graphics._onVideoLoad; Graphics._onVideoLoad = function() { _Graphics__onVideoLoad.apply(this, arguments); if (this._needVideoStop) { this._needVideoStop = false; this.stopVideo(); } else { this.setVideoContentsScale(this._video.scaleX, this._video.scaleY); } }; var _Graphics__updateVideo = Graphics._updateVideo; Graphics._updateVideo = function() { var prevVideo = this._video; this._video = this._videoFrame; _Graphics__updateVideo.apply(this, arguments); this._video = prevVideo; this._updateVideoContents(); }; Graphics.setVideoContentsPosition = function(x, y) { this._video.x = x; this._video.y = y; this._updateVideoContents(); }; Graphics.setVideoContentsScale = function(scaleX, scaleY) { this._video.scaleX = scaleX; this._video.scaleY = scaleY; this._video.width = (this._videoScaleFitScreen ? this._width : this._video.videoWidth) * scaleX; this._video.height = (this._videoScaleFitScreen ? this._height : this._video.videoHeight) * scaleY; this._updateVideoContents(); }; Graphics._updateVideoContents = function() { var video = this._video; video.style.width = video.width * this._realScale + 'px'; video.style.height = video.height * this._realScale + 'px'; video.style.left = video.x * this._realScale + 'px'; video.style.top = video.y * this._realScale + 'px'; }; //============================================================================= // Game_Interpreter // プラグインコマンドを追加定義します。 //============================================================================= var _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand; Game_Interpreter.prototype.pluginCommand = function(command, args) { _Game_Interpreter_pluginCommand.apply(this, arguments); if (!command.match(new RegExp('^' + metaTagPrefix))) return; this.pluginCommandMovieManager(command.replace(metaTagPrefix, ''), args); }; Game_Interpreter.prototype.pluginCommandMovieManager = function(command, args) { var waitTime = 0; switch (getCommandName(command)) { case '設定_ループ': case 'SETTING_LOOP': MovieManager.setLoop(getArgBoolean(args[0])); break; case '設定_画面に合わせる': case 'SETTING_FIT_SCREEN': MovieManager.setScaleFitScreen(getArgBoolean(args[0])); break; case '設定_再生速度': case 'SETTING_PLAY_RATE': MovieManager.setPlaybackRate(getArgFloat(args[0], 0)); break; case '設定_再生位置': case 'SETTING_CURRENT_TIME': MovieManager.setCurrentTime(getArgFloat(args[0], 0)); break; case '移動_不透明度': case 'MOVE_OPACITY': waitTime = getArgNumber(args[1], 0); MovieManager.moveOpacity(getArgNumber(args[0], 0, 256), waitTime); if (getArgBoolean(args[2])) this.wait(waitTime); break; case '移動_座標': case 'MOVE_POSITION': waitTime = getArgNumber(args[2], 0); MovieManager.movePosition(getArgNumber(args[0]), getArgNumber(args[1]), waitTime); if (getArgBoolean(args[3])) this.wait(waitTime); break; case '移動_拡大率': case 'MOVE_SCALE': waitTime = getArgNumber(args[2], 0); MovieManager.moveScale(getArgNumber(args[0]), getArgNumber(args[1]), waitTime); if (getArgBoolean(args[3])) this.wait(waitTime); break; case '停止': case 'STOP': MovieManager.stop(); break; case 'ウェイト': case 'WAIT': this.setWaitMode('video'); break; case '一時停止': case 'PAUSE': MovieManager.pause(); break; case '再生': case 'PLAY': MovieManager.play(); break; } }; var _Game_Interpreter_command261 = Game_Interpreter.prototype.command261; Game_Interpreter.prototype.command261 = function() { var result = _Game_Interpreter_command261.apply(this, arguments); this._waitMode = ''; $gameTemp.sabaWaitForMovieMode = 0; return result; }; var _Game_Interpreter_command354 = Game_Interpreter.prototype.command354; Game_Interpreter.prototype.command354 = function() { MovieManager.stop(); return _Game_Interpreter_command354.apply(this, arguments); }; //============================================================================= // SceneManager // 動画管理モジュールを操作します。 //============================================================================= var _SceneManager_initialize = SceneManager.initialize; SceneManager.initialize = function() { _SceneManager_initialize.apply(this, arguments); MovieManager.initTarget(); }; var _SceneManager_updateScene = SceneManager.updateScene; SceneManager.updateScene = function() { _SceneManager_updateScene.apply(this, arguments); MovieManager.update(); }; //============================================================================= // MovieManager // 動画管理モジュールです。 //============================================================================= MovieManager.initTarget = function() { this._targetX = this.getPositionX(); this._targetY = this.getPositionY(); this._durationPosition = 0; this._targetScaleX = this.getScaleX(); this._targetScaleY = this.getScaleY(); this._durationScale = 0; this._targetOpacity = this.getOpacity(); this._durationOpacity = 0; }; MovieManager.update = function() { this.updatePosition(); this.updateScale(); this.updateOpacity(); }; MovieManager.updatePosition = function() { if (this._durationPosition > 0) { var x = this.getPositionX(); var y = this.getPositionY(); var d = this._durationPosition; x = (x * (d - 1) + this._targetX) / d; y = (y * (d - 1) + this._targetY) / d; this.setPosition(x, y); this._durationPosition--; } }; MovieManager.updateScale = function() { if (this._durationScale > 0) { var sx = this.getScaleX(); var sy = this.getScaleY(); var d = this._durationScale; sx = (sx * (d - 1) + this._targetScaleX) / d; sy = (sy * (d - 1) + this._targetScaleY) / d; this.setScale(sx, sy); this._durationScale--; } }; MovieManager.updateOpacity = function() { if (this._durationOpacity > 0) { var opacity = this.getOpacity(); var d = this._durationOpacity; opacity = (opacity * (d - 1) + this._targetOpacity) / d; this.setOpacity(opacity); this._durationOpacity--; } }; MovieManager.getVideo = function() { return Graphics.getVideo(); }; MovieManager.isPlaying = function() { return Graphics._isVideoVisible(); }; MovieManager.play = function() { if (!Graphics.isVideoLoading()) { this.getVideo().play(); } }; MovieManager.pause = function() { this.getVideo().pause(); }; MovieManager.stop = function() { Graphics.stopVideo(); this.initTarget(); }; MovieManager.setLoop = function(value) { this.getVideo().loop = !!value; }; MovieManager.getLoop = function() { return this.getVideo().loop; }; MovieManager.setScaleFitScreen = function(value) { Graphics.setVideoScaleFitScreen(!!value); }; MovieManager.setCurrentTime = function(value) { this.getVideo().currentTime = value; }; MovieManager.getCurrentTime = function() { return this.getVideo().currentTime; }; MovieManager.setPlaybackRate = function(value) { this.getVideo().playbackRate = value; }; MovieManager.getPlaybackRate = function() { return this.getVideo().playbackRate; }; MovieManager.moveOpacity = function(opacity, duration) { if (duration === 0) { this.setOpacity(opacity); } else { this._targetOpacity = opacity; this._durationOpacity = duration; } }; MovieManager.setOpacity = function(opacity) { var realOpacity = opacity / 256; if (realOpacity !== this.getOpacity()) { this.getVideo().style.opacity = String(realOpacity); } }; MovieManager.getOpacity = function() { return this.getVideo().style.opacity * 256; }; MovieManager.moveScale = function(scaleX, scaleY, duration) { if (duration === 0) { this.setScale(scaleX, scaleY); } else { this._targetScaleX = scaleX; this._targetScaleY = scaleY; this._durationScale = duration; } }; MovieManager.setScale = function(scaleX, scaleY) { if (scaleX !== this.getScaleX() || scaleY !== this.getScaleY()) { Graphics.setVideoContentsScale(scaleX / 100, scaleY / 100); } }; MovieManager.getScaleX = function() { return this.getVideo().scaleX * 100; }; MovieManager.getScaleY = function() { return this.getVideo().scaleY * 100; }; MovieManager.movePosition = function(x, y, duration) { if (duration === 0) { this.setPosition(x, y); } else { this._targetX = x; this._targetY = y; this._durationPosition = duration; } }; MovieManager.setPosition = function(x, y) { if (this.getPositionX() !== x || this.getPositionY() !== y) { Graphics.setVideoContentsPosition(x, y); } }; MovieManager.getPositionX = function() { return this.getVideo().x; }; MovieManager.getPositionY = function() { return this.getVideo().y; }; })();