show-first/js/plugins/DarkPlasma_AutoHighlight.js
2024-08-08 11:24:10 -05:00

265 lines
8 KiB
JavaScript

// DarkPlasma_AutoHighlight 2.0.1
// Copyright (c) 2022 DarkPlasma
// This software is released under the MIT license.
// http://opensource.org/licenses/mit-license.php
/**
* 2024/01/15 2.0.1 ビルド方式を変更 (configをTypeScript化)
* 2023/06/02 2.0.0 色設定をMZ1.6.0形式に変更
* ベースプラグインを追加
* TypeScript移行
* 2022/06/08 1.0.1 対象ウィンドウのクラス名がグローバルに展開されていなくても有効にする
* 2022/01/02 1.0.0 公開
*/
/*:
* @plugindesc 指定した語句に自動で色をつける
* @author DarkPlasma
* @license MIT
*
* @target MZ
* @url https://github.com/elleonard/DarkPlasma-MZ-Plugins/tree/release
*
* @base DarkPlasma_SetColorByCode
*
* @param highlightGroups
* @desc ハイライトする際の色と語句を設定します。
* @text 色と語句
* @type struct<HighlightGroup>[]
* @default []
*
* @param targetWindows
* @desc 自動ハイライトの対象となるウィンドウクラスを指定します。
* @text 対象ウィンドウ
* @type string[]
* @default ["Window_Message"]
*
* @help
* version: 2.0.1
* 指定した語句を指定した色でハイライトします。
*
* 本プラグインの利用には下記プラグインを必要とします。
* DarkPlasma_SetColorByCode version:1.0.0
*/
/*~struct~HighlightGroup:
* @param title
* @desc 色と語句設定の管理用の名前を指定します。わかりやすい名前をつけてください。
* @text 名前
* @type string
*
* @param color
* @desc 色を指定します。#から始まるカラーコードも指定可能です。
* @text 色
* @type color
* @default 0
*
* @param texts
* @desc ハイライトしたい語句を指定します。
* @text 語句
* @type string[]
* @default []
*
* @param skills
* @desc 名前をハイライトしたいスキルを指定します。
* @text スキル
* @type skill[]
* @default []
*
* @param items
* @desc 名前をハイライトしたいアイテムを指定します。
* @text アイテム
* @type item[]
* @default []
*/
(() => {
"use strict";
const pluginName = document.currentScript.src.replace(
/^.*\/(.*).js$/,
function () {
return arguments[1];
}
);
const pluginParametersOf = (pluginName) =>
PluginManager.parameters(pluginName);
const pluginParameters = pluginParametersOf(pluginName);
const settings = {
highlightGroups: pluginParameters.highlightGroups
? JSON.parse(pluginParameters.highlightGroups).map((e) => {
return e
? ((parameter) => {
const parsed = JSON.parse(parameter);
return {
title: String(parsed.title || ``),
color: parsed.color?.startsWith("#")
? String(parsed.color)
: Number(parsed.color || 0),
texts: parsed.texts
? JSON.parse(parsed.texts).map((e) => {
return String(e || ``);
})
: [],
skills: parsed.skills
? JSON.parse(parsed.skills).map((e) => {
return Number(e || 0);
})
: [],
items: parsed.items
? JSON.parse(parsed.items).map((e) => {
return Number(e || 0);
})
: [],
};
})(e)
: { title: "", color: 0, texts: [], skills: [], items: [] };
})
: [],
targetWindows: pluginParameters.targetWindows
? JSON.parse(pluginParameters.targetWindows).map((e) => {
return String(e || ``);
})
: ["Window_Message"],
};
function ColorManagerMixIn(colorManager) {
colorManager.convertColorParameter = function (colorParameter) {
return typeof colorParameter === "string"
? colorParameter
: this.textColor(colorParameter);
};
}
ColorManagerMixIn(ColorManager);
class HighlightWords {
constructor() {
this._highlightWords = [];
this._sortedWords = null;
this._colors = {};
this._needsRefreshCache = false;
}
getRegExp() {
return new RegExp(`(${this.sortedWords().join("|")})`, "gi");
}
/**
* 長さ順にソートしたハイライト語句一覧
*/
sortedWords() {
if (!this._sortedWords || this._needsRefreshCache) {
this.refreshCache();
}
return this._sortedWords || [];
}
/**
* @param {HighlightWord} highlightWord ハイライトする語句と色
*/
add(highlightWord) {
this._highlightWords.push(highlightWord);
this._needsRefreshCache = true;
}
refreshCache() {
/**
* 毎度ソートするのはパフォーマンス的に許容できないため、キャッシュする
*/
this._sortedWords = this._highlightWords
.map((word) => word.word)
.sort((a, b) => b.length - a.length);
this._colors = {};
/**
* パフォーマンスに気を使い、ランダムアクセスできるようにキャッシュする
*/
this._highlightWords.forEach((highlightWord) => {
this._colors[highlightWord.word] = highlightWord.color;
});
this._needsRefreshCache = false;
}
/**
* ハイライト色を返す
* @param {string} word ハイライトする語句
* @return {string|number}
*/
findColorByWord(word) {
if (!this._colors) {
this.refreshCache();
}
return this._colors[word];
}
/**
* テキスト内の指定語句をハイライトして返す
* @param {string} text ハイライト対象テキスト
* @return {string}
*/
highlightText(text) {
return text.replace(this.getRegExp(), (match) => {
return `\x1bC[${this.findColorByWord(match)}]${match}\x1bC[0]`;
});
}
}
class HighlightWord {
constructor(word, color) {
this._word = word;
this._color = color;
}
get word() {
return this._word;
}
get color() {
return ColorManager.convertColorParameter(this._color);
}
}
const highlightWords = new HighlightWords();
/**
* @param {Scene_Boot.prototype} sceneBoot
*/
function Scene_Boot_AutoHighlightMixIn(sceneBoot) {
const _start = sceneBoot.start;
sceneBoot.start = function () {
_start.call(this);
/**
* データベースのロードが完了しているので、ハイライトテキストを設定する。
*/
settings.highlightGroups.forEach((highlightGroup) => {
highlightGroup.texts.forEach((text) => {
if (text) {
highlightWords.add(new HighlightWord(text, highlightGroup.color));
}
});
highlightGroup.skills.forEach((skillId) => {
const skillName = $dataSkills[skillId].name;
if (skillName) {
highlightWords.add(
new HighlightWord(skillName, highlightGroup.color)
);
}
});
highlightGroup.items.forEach((itemId) => {
const itemName = $dataItems[itemId].name;
if (itemName) {
highlightWords.add(
new HighlightWord(itemName, highlightGroup.color)
);
}
});
});
};
}
Scene_Boot_AutoHighlightMixIn(Scene_Boot.prototype);
function Window_AutoHighlightMixIn(windowClass) {
const _convertEscapeCharacters = windowClass.convertEscapeCharacters;
windowClass.convertEscapeCharacters = function (text) {
text = _convertEscapeCharacters.call(this, text);
if (this.isHighlightWindow()) {
return highlightWords.highlightText(text);
}
return text;
};
windowClass.isHighlightWindow = function () {
return settings.targetWindows.some(
(targetWindow) => this.constructor.name === targetWindow
);
};
}
Window_AutoHighlightMixIn(Window_Base.prototype);
})();