バックログ表示プラグイン
//=============================================================================
// Lunatlazur_BackLog.js
// ----------------------------------------------------------------------------
// Copyright (c) 2019 Taku Aoi
// This plugin is released under the zlib License.
// https://zlib.net/zlib_license.html
// ----------------------------------------------------------------------------
// Version
// 1.1.0 2021-05-16
// ----------------------------------------------------------------------------
// [Web] : https://lunatlazur.com
// [Twitter]: https://twitter.com/aoitaku
// [GitHub] : https://github.com/lunatlazur
//=============================================================================
/*:
* @plugindesc Show message back log
* @author Taku Aoi
* @help This plugin shows message back log.
*
* Usage
* =====
*
* The backlog feature is enabled by default when you install the plugin.
* To disable or re-enable the backlog function, use the plug-in command
* to enable / disable it.
*
*
* Plug-in command list
* ====================
*
* ENABLE_BACKLOG
* --------------
*
* ENABLE_BACKLOG
*
* Enable backlog.
* The backlog is displayed by scrolling up the mouse wheel or pressing
* the PageUp key.
*
* DISABLE_BACKLOG
* ---------------
*
* DISABLE_BACKLOG
*
* Disable the backlog.
* The backlog is not displayed even if the mouse wheel is scrolled up
* or the PageUp key is entered.
*
*
* Changelog
* =========
*
* 1.1.0 2021-05-16
* ----------------
* - Added plugin parameters to choose whether to make the backlog
* layout 2 columns
*
* 1.0.0 2019-12-21
* ----------------
* - Published.
*
*
* @param 2-columns layout
* @desc Select whether to display the backlog in two columns.
* `Yes` to diplay in two columns.
* @type boolean
* @on Yes
* @off No
* @default true
*/
/*:ja
* @plugindesc バックログ表示プラグイン
* @author あおいたく
* @help このプラグインはバックログを表示できるようにします。
*
* 名前ウィンドウ表示プラグイン、メッセージ表示継続プラグインと同時に使う場合は、
* 本プラグインを上記プラグインよりも下に配置してください。
*
* 使い方
* ======
*
* プラグインを導入した状態では、バックログ機能はデフォルトで有効になっています。
* バックログ機能を無効化したり再度有効化したりする場合は、プラグインコマンドで
* 適宜、有効・無効の切替を行ってください。
*
*
* プラグインコマンド一覧
* ======================
*
* バックログの有効化
* ------------------
*
* バックログの有効化
*
* バックログを有効化します。
* 以降、マウスホイールのスクロールアップや PageUp キーの入力でバックログを
* 表示することができます。
*
*
* バックログの無効化
* ------------------
*
* バックログの無効化
*
* バックログを無効化します。
* 以降、マウスホイールのスクロールアップや PageUp キーの入力でバックログを
* 表示できなくなります。
*
*
* 変更履歴
* ========
*
* 1.1.0 2021-05-16
* ----------------
* - 2カラムレイアウトにするかどうか選択できるようにプラグインパラメータを追加
*
* 1.0.0 2019-12-21
* ----------------
* - 公開
*
*
* @param 2カラムレイアウト
* @desc バックログの表示を2カラムにするかどうかを選択します。
* `する` で2カラムで表示します。
* @type boolean
* @on する
* @off しない
* @default true
*/
(function () {
'use strict';
const pluginName = 'Lunatlazur_BackLog';
function getValue(params, ...names) {
let found = null;
names.forEach((name) => {
if (!!params[name]) {
found = params[name];
}
});
return found;
}
function asNumber(params, ...names) {
return parseInt(getValue(params, ...names), 10);
}
function asBoolean(params, ...names) {
const value = getValue(params, ...names).toLowerCase();
return value === 'true' || value === 'on';
}
const parameters = PluginManager.parameters(pluginName);
const maxNumberOfMessages = 100;
const isMultiColumnLayout = asBoolean(parameters, '2カラムレイアウト', '2-columns layout');
const actorNameWindowPlugin = {
enabled: false,
};
if (PluginManager._scripts.includes('Lunatlazur_ActorNameWindow')) {
actorNameWindowPlugin.enabled = true;
const parameters = PluginManager.parameters('Lunatlazur_ActorNameWindow');
actorNameWindowPlugin.params = {
textColor: asNumber(parameters, 'テキストカラー'),
horizontalOffset: asNumber(parameters, '水平位置'),
};
}
const _Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function (command, args) {
_Game_Interpreter_pluginCommand.apply(this, arguments);
switch ((command || '').toUpperCase()) {
case 'ENABLE_BACKLOG':
case 'バックログの有効化':
BackLogManager.enable();
break;
case 'DISABLE_BACKLOG':
case 'バックログの無効化':
BackLogManager.disable();
break;
}
};
class BackLogManager {
static initialize() {
this._backLog = { rows: [] };
this._hiddenWindows = [];
this._enabled = true;
this._busy = false;
}
static makeSaveContents() {
return {
enabled: this._enabled,
};
}
static extractSaveContents(contents) {
if (contents.backLogState) {
this._enabled = contents.backLogState.enabled;
}
}
static get numberOfRows() {
return this._backLog.rows.length;
}
static get hiddenWindows() {
return this._hiddenWindows;
}
static get disabled() {
return !this._enabled;
}
static enable() {
this._enabled = true;
}
static disable() {
this._enabled = false;
}
static pushRow(text, actorName) {
if (maxNumberOfMessages <= this.numberOfRows) {
this._backLog.rows.shift();
}
this._backLog.rows.push({ text, actorName });
}
static pushHiddenWindow(...windows) {
this._hiddenWindows.push(...windows);
}
static clearHiddenWindows() {
this._hiddenWindows = [];
}
static clearRows() {
this._backLog.rows = [];
}
static scrolledContent(offset, length) {
return [...this._backLog.rows].reverse().slice(offset, offset + length);
}
static isBusy() {
return this._busy;
}
static setBusy(busy) {
this._busy = busy;
}
}
BackLogManager._backLog = {
rows: [],
};
BackLogManager._hiddenWindows = [];
BackLogManager._enabled = true;
BackLogManager._busy = false;
const DataManager_createGameObjects = DataManager.createGameObjects;
DataManager.createGameObjects = function () {
DataManager_createGameObjects.apply(this, arguments);
BackLogManager.initialize();
};
const DataManager_makeSaveContents = DataManager.makeSaveContents;
DataManager.makeSaveContents = function () {
const contents = DataManager_makeSaveContents.call(this);
contents.backLogState = BackLogManager.makeSaveContents();
return contents;
};
const DataManager_extractSaveContents = DataManager.extractSaveContents;
DataManager.extractSaveContents = function (contents) {
DataManager_extractSaveContents.apply(this, arguments);
BackLogManager.extractSaveContents(contents);
};
const Scene_Map_createDisplayObjects = Scene_Map.prototype.createDisplayObjects;
Scene_Map.prototype.createDisplayObjects = function () {
Scene_Map_createDisplayObjects.call(this);
this._backLogWindow = new Window_BackLog();
this.addChild(this._backLogWindow);
};
const Scene_Map_update = Scene_Map.prototype.update;
Scene_Map.prototype.update = function () {
const threshold = 20;
if (this._backLogWindow.visible) {
this._backLogWindow.update();
return;
}
Scene_Map_update.call(this);
if (BackLogManager.disabled) {
return;
}
if (this._messageWindow.isClosing() || this._messageWindow.isOpening()) {
return;
}
if (this._scrollTextWindow.visible) {
return;
}
if (Input.isTriggered('pageup') || TouchInput.wheelY <= -threshold) {
if (this._messageWindow.isOpen()) {
BackLogManager.pushHiddenWindow(this._messageWindow);
const visibleWindows = [...this._messageWindow.subWindows()].filter((window) => {
return window.visible;
});
if (!this._messageWindow._hideMessageManager) {
visibleWindows.forEach((window) => window.hide());
BackLogManager.pushHiddenWindow(...visibleWindows);
}
this._messageWindow._showFast = true;
this._messageWindow.hide();
}
if (this._mapNameWindow.isOpen()) {
BackLogManager.pushHiddenWindow(this._mapNameWindow);
this._mapNameWindow.hide();
}
this._backLogWindow.offset = 0;
this._backLogWindow.show();
}
};
const Window_Message_startMessage = Window_Message.prototype.startMessage;
Window_Message.prototype.startMessage = function () {
Window_Message_startMessage.call(this);
if (BackLogManager.isBusy()) {
return;
}
BackLogManager.setBusy(true);
const lines = this._textState.text.split('\n');
const numVisibleRows = this.numVisibleRows();
lines.reduce((prev, _, index) => {
return (index % numVisibleRows ? prev : [...prev, lines.slice(index, index + numVisibleRows).join('\n')]);
}, []).forEach((row) => {
BackLogManager.pushRow(row, this._nameWindow && this._nameWindow.visible && this._nameWindow._text);
});
};
const Window_Message_terminateMessage = Window_Message.prototype.terminateMessage;
Window_Message.prototype.terminateMessage = function () {
BackLogManager.setBusy(false);
Window_Message_terminateMessage.call(this);
};
class Window_BackLog extends Window_Base {
constructor(_) {
super();
this.initialize.apply(this, arguments);
}
initialize(fontSize) {
super.initialize(0, 0, Graphics.width, Graphics.height);
this._fontSize = fontSize || 28;
this.offset = 0;
this._stayCount = 0;
this._touching = false;
this.deactivate();
this.hide();
}
messageWindow() {
return SceneManager._scene._messageWindow;
}
standardPadding() {
return 4;
}
standardFontSize() {
return this._fontSize;
}
standardFontFace() {
return Window_Message.prototype.standardFontFace.call(this);
}
rowHeight() {
const padding = 18;
let rowsPerMessage;
if (isMultiColumnLayout) {
rowsPerMessage = this.messageWindow().numVisibleRows();
}
else {
rowsPerMessage = this.messageWindow().numVisibleRows() + (actorNameWindowPlugin.enabled ? 1 : 0);
}
return this.lineHeight() * rowsPerMessage + padding * 2;
}
numVisibleRows() {
return Math.floor(Graphics.height / this.rowHeight());
}
update() {
Window_Base.prototype.update.call(this);
this.updateArrows();
this.processHandling();
this.processWheel();
this.processTouch();
this._stayCount++;
}
updateArrows() {
this.downArrowVisible = this.offset > 0;
this.upArrowVisible = this.offset < BackLogManager.numberOfRows - 1;
}
_refreshArrows() {
Window.prototype._refreshArrows.call(this);
this._downArrowSprite.move(this.width - 16, this._downArrowSprite.y);
this._upArrowSprite.move(this.width - 16, this._upArrowSprite.y);
}
refresh() {
this.createContents();
this.contents.clear();
this.resetFontSettings();
this.updateArrows();
this.drawRows(this.offset);
this._stayCount = 0;
}
rewind() {
if (this.offset > 0) {
this.offset -= 1;
this.refresh();
}
}
forward() {
if (this.offset < BackLogManager.numberOfRows - 1) {
this.offset += 1;
this.refresh();
}
}
rewindPage() {
const offset = this.offset;
this.offset -= this.numVisibleRows();
if (this.offset < 0) {
this.offset = 0;
}
if (offset !== this.offset) {
this.refresh();
}
}
forwardPage() {
const offset = this.offset;
this.offset += this.numVisibleRows();
if (this.offset >= BackLogManager.numberOfRows) {
this.offset = BackLogManager.numberOfRows - 1;
}
if (offset !== this.offset) {
this.refresh();
}
}
isCancelTriggered() {
return Input.isRepeated('cancel');
}
processHandling() {
if (Input.isRepeated('up')) {
this.forward();
}
if (Input.isRepeated('down')) {
this.rewind();
}
if (this.isCancelTriggered()) {
this.processCancel();
}
else if (Input.isTriggered('pageup')) {
this.forwardPage();
}
else if (Input.isTriggered('pagedown')) {
this.rewindPage();
}
}
processCancel() {
this.hide();
BackLogManager.hiddenWindows.forEach((window) => {
window.show();
});
BackLogManager.clearHiddenWindows();
}
processWheel() {
if (this.isOpen()) {
const threshold = 20;
if (TouchInput.wheelY >= threshold) {
this.rewind();
}
if (TouchInput.wheelY <= -threshold) {
this.forward();
}
}
}
isTouchedInsideFrame() {
var x = this.canvasToLocalX(TouchInput.x);
var y = this.canvasToLocalY(TouchInput.y);
return x >= 0 && y >= 0 && x < this.width && y < this.height;
}
processTouch() {
if (this.isOpen()) {
if (TouchInput.isTriggered() && this.isTouchedInsideFrame()) {
this._touching = true;
this.onTouch();
}
else if (TouchInput.isCancelled()) {
this.processCancel();
}
if (this._touching) {
if (TouchInput.isPressed()) {
this.onTouch();
}
else {
this._touching = false;
}
}
}
else {
this._touching = false;
}
}
onTouch() {
const x = this.canvasToLocalX(TouchInput.x);
const y = this.canvasToLocalY(TouchInput.y);
if (this._stayCount > 10 && x >= this.width - 20) {
if (y < 20) {
this.forward();
}
else if (y >= this.height - 20) {
this.rewind();
}
}
}
show() {
this.refresh();
super.show();
}
drawRows(offset) {
const rows = BackLogManager.scrolledContent(offset, this.numVisibleRows() + 1);
const x = 14;
const marginY = (this.lineHeight() - 2) / 2;
const lastFontSize = this._fontSize;
if (isMultiColumnLayout && actorNameWindowPlugin.enabled) {
const ratio = (this.contentsWidth() - 168) / this.contentsWidth();
this._fontSize = lastFontSize * ratio;
this.contents.fontSize = this._fontSize;
}
rows.forEach((row, index) => {
const y = this.contentsHeight() - marginY - this.rowHeight() * (index + 1);
this.contents.fillRect(0, y + marginY, this.contentsWidth(), 2, this.textColor(8));
if (isMultiColumnLayout) {
if (actorNameWindowPlugin.enabled) {
if (row.actorName) {
this.changeTextColor(this.textColor(actorNameWindowPlugin.params.textColor));
this.drawText(row.actorName, x, y + this.lineHeight());
}
this.drawTextEx(row.text, x + 168, y + this.lineHeight());
}
else {
this.drawTextEx(row.text, x, y + this.lineHeight());
}
}
else {
if (actorNameWindowPlugin.enabled && row.actorName) {
this.changeTextColor(this.textColor(actorNameWindowPlugin.params.textColor));
this.drawText(row.actorName, x, y + this.lineHeight());
}
this.drawTextEx(row.text, x, y + this.lineHeight() * (actorNameWindowPlugin.enabled ? 2 : 1));
}
});
this._fontSize = lastFontSize;
}
}
}());
このプラグインはメッセージのバックログを表示できるようにします。
利用方法
マウスホイールのスクロールアップや PageUp
キーを入力することでバックログを表示できます。
名前ウィンドウ表示プラグイン、メッセージ表示継続プラグインと同時に使う場合は、本プラグインを上記プラグインよりも下に配置してください。
プラグインを導入した状態では、バックログ機能はデフォルトで有効になっています。
バックログ機能を無効化したり再度有効化したりする場合は、プラグインコマンドで適宜、有効・無効の切替を行ってください。
プラグインコマンドの詳細はプラグインコマンド一覧を参照してください。
プラグインコマンド一覧
バックログの有効化
- 呼び出し形式
-
バックログの有効化
バックログを有効化します。
以降、マウスホイールのスクロールアップやPageUp
キーの入力でバックログを表示することができます。
バックログの無効化
- 呼び出し形式
-
バックログの無効化
バックログを無効化します。
以降、マウスホイールのスクロールアップやPageUp
キーの入力でバックログを表示しないうようになります。
変更履歴
1.1.0 2021-05-16
- 2カラムレイアウトにするかどうか選択できるようにプラグインパラメータを追加
1.0.0 2019-12-21
- 公開
ライセンス
このプラグインは zlib ライセンス のもと配布されます。
Copyright © 2019 あおいたく / Lunatlazur
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
- The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
- Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
- This notice may not be removed or altered from any source distribution.