alter-egoism/js/plugins/Live2DInterfaceMZ.js
2025-11-01 14:17:42 -05:00

1538 lines
43 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Copyright(c) Live2D Inc. All rights reserved.
*
* Use of this source code is governed by the Live2D Open Software license
* that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
*/
/* 更新履歴
* Slip 2021/07/11 ツクールMZ用プラグイン向けに作成ベースはツクールMV用のLive2Dプラグイン
* Slip 2021/08/14 表情変更機能を追加
*
* 本プラグインの再配布、改変はLive2D Open Software licenseに準拠します。
*
* Live2D Open Software 使用許諾契約書
* https://www.live2d.com/eula/live2d-open-software-license-agreement_jp.html
*/
/*:
* @plugindesc Plug-in that displays live2d on Maker MV
* ツクールMZ上でlive2dを立ち絵表示するプラグイン
* @author Slip
*
* @param Modelcondition
* @desc live2d model individual setting
* live2dモデル個別設定
* @default
* @type struct<ModelconditionData>[]
*
* @param ModelPosition
* @type note
* @default Model placement
* @desc Model placement
* モデル配置
*
* @param ModelScaling
* @type note
* @default Scale model
* @desc Scale model
* モデルの拡大・縮小
*
* @param System
* @type note
* @default System
* @desc System
* システム関連
*
* @param vertical
* @type number
* @desc Vertical display position
* 縦の表示位置
* @default 320
* @min 0
* @max 640
* @parent ModelPosition
*
* @param left
* @type number
* @desc Horizontal display position (left)
* 横の表示位置(左)
* @default 100
* @min 0
* @max 816
* @parent ModelPosition
*
* @param middle
* @type number
* @desc Horizontal display position (center)
* 横の表示位置(中央)
* @default 408
* @min 0
* @max 1200
* @parent ModelPosition
*
* @param right
* @type number
* @desc Horizontal display position (right)
* 横の表示位置(右)
* @default 716
* @min 0
* @max 816
* @parent ModelPosition
*
* @param DefaultScale
* @type string
* @desc Model size initial value
* モデルの大きさ初期値
* @default 1.0
* @parent ModelScaling
*
* @param pictpriority
* @type number
* @desc The live2d model is displayed before the picture below this ID.
* このID以下のピクチャよりも手前にlive2dのモデルを表示します。
* @min 0
* @max 100
* @default 10
* @parent System
*
* @param includesave
* @desc Include the display status of live2d in save data
* live2dの表示状況をセーブデータに含める
* @default true
* @type boolean
* @parent System
*
* @param useinbattle
* @desc Live2d model use flag in battle scene
* 戦闘画面でのlive2dモデル使用フラグ
* @default false
* @type boolean
* @parent System
*
*
* @command show
* @text 表示
* @desc 指定したモデルを表示します
*
* @arg modelName
* @type string
* @default
*
* @command hide
* @text 消去
* @desc 指定したモデルを消去します
*
* @arg modelName
* @type string
* @default
*
* @command motion
* @text モーション再生
* @desc 指定したモデルのモーションを再生します
*
* @arg modelName
* @type string
* @desc モデル名
* @default
*
* @arg motionName
* @type string
* @desc モーション名
* @default
*
* @arg loop
* @type boolean
* @desc ループする/しない
* @default false
*
* @command expression
* @text 表情変更
* @desc 指定したモデルの表情を変更します
*
* @arg modelName
* @type string
* @desc モデル名
* @default
*
* @arg expressionName
* @type string
* @desc model3.json "Expressions"のName
* @default 1
*
* @command pos
* @text 位置変更
* @desc 指定したモデルの位置を変更します
*
* @arg modelName
* @type string
* @default
* @desc モデル名
*
* @arg x
* @type number
* @default 408
* @desc X位置
*
* @arg y
* @type number
* @default 312
* @desc Y位置
*
* @arg dur
* @type number
* @default 1
* @desc 移動時間
*
* @arg wait
* @type boolean
* @default false
* @desc ウェイトありなし
*
* @command left
* @text 左
* @desc 指定したモデル位置を左にします。
*
* //引数
* @arg modelName
* @type string
* @default
*
* @command middle
* @text 真ん中
* @desc 指定したモデル位置を真ん中にします。
*
* //引数
* @arg modelName
* @type string
* @default
*
* @command right
* @text 右
* @desc 指定したモデル位置を右にします。
*
* //引数
* @arg modelName
* @type string
* @default
*
* @command scale
* @text 倍率変更
* @desc 指定したモデルの倍率を変更します
*
* @arg modelName
* @type string
* @default
*
* @arg scale
* @type Number
* @default
*
* @command paraminitskip
* @text モーション強制初期化
* @desc モーション再生時にモデルパラメータを初期化します
*
*
* @command cloth_act
* @text 服装反映させる
* @desc モーション再生時にパラメータ24の値を変数によって変更します
*
* @arg modelName
* @type string
* @default
*
* @arg IsInit
* @type boolean
* @default true
*
* @arg actor
* @type string
* @default
* @desc 白雪:sira 夜鶴:yozu
*
*
* @command bote_act
* @text ボテ腹を反映させる(エロステ)
* @desc モーション再生時にパラメータ24の値を変数によって変更します
*
* @arg modelName
* @type string
* @default
*
* @arg IsInit
* @type boolean
* @default true
*
* @arg actor
* @type string
* @default
* @desc 白雪:sira 夜鶴:yozu
*
*
* @help
* [English]
* live2d standing picture display plugin ver1.0.0
*
* It is a plug-in that displays a live2d (cubism 4.0) model while standing and talking.
*
* Usage:
* ↓ It is described here.
* https://github.com/MrSlip777/plugins_talk_live2d_cubism4/blob/master/README_en.md
*
* [日本語]
* live2d立ち絵表示プラグイン ver1.0.0
*
* live2d(cubism4.0)のモデルを会話中に立ち絵表示するプラグインです。
*
* 使い方:
* ↓こちらに記載しています。
* https://github.com/MrSlip777/plugins_talk_live2d_cubism4/blob/master/README.md
*/
/*~struct~ModelconditionData:
* @param Modelname
* @desc The name of the model used in the plugin command
* プラグインコマンドで使用するモデルの名前
* @default
*
* @param folderpath
* @desc folder path of model3.json file
* model3.jsonファイルのフォルダパス
* @default
*
* @param motiongroupnames
* @desc You can set the name of the motion.
* モーションの名称を設定できます。
* @type note
* @default "<basic:Idle_1,Idle_3>\n<angry:Idle_4>"
*
*/
/**
* //一旦保留
*
* @param PlayBack
* @type note
* @default Motion playback
* @desc Motion playback
* モーション再生
*
* @param LinkEquipment
* @type note
* @default Linked setting with equipment
* @desc Linked setting with equipment.
* 装備品との連動設定
*
* @param upsidedown
* @type boolean
* @desc Upside down display
* 上下反転表示
* @default false
* @parent Screen
*
* @param playbackSpeed
* @type number
* @desc Playback speed
* 再生速度
* @default 8
* @parent PlayBack
*
* @param AdjustWeight
* @type number
* @desc Deformation weight adjustment parameter
* 変形の重み調整パラメータ
* @default 8
* @parent PlayBack
* @param Scene
* @type note
* @default Scenes such as maps and battle screens
* @desc Scenes such as maps and battle screens
* マップ、戦闘画面等のシーン
*
* @param SaveData
* @type note
* @default Save data
* @desc Save data
* セーブデータ
*
* @param ScaleGain
* @type number
* @desc Scaling growth rate
* 拡大縮小の増加率
* @default 2
* @parent ModelScaling
*
*
* @param useLinkEquipment
* @desc use flag LinkEquipment.
* 装備品との連動フラグ
* @default false
* @type boolean
* @parent LinkEquipment
*
* @param individual_upsidedown
* @type boolean
* @desc Individual upside down flag
* 個々の上下反転フラグ
* @default false
*
* @param SettingLinkEquipment
* @type note
* @default 装備とのモーション連動設定
* @desc Linked setting with equipment.
* 装備とのモーション連動設定
*
* @param noWeapon
* @desc Motion without weapon.
* 武器なし時のモーション
* @default
* @parent SettingLinkEquipment
*
* @param noShield
* @desc Motion without shield.
* 盾なし時のモーション
* @default
* @parent SettingLinkEquipment
*
* @param noHead
* @desc Motion without head armor.
* 頭防具なし時のモーション
* @default
* @parent SettingLinkEquipment
*
* @param noBody
* @desc Motion without body armor.
* 体防具なし時のモーション
* @default
* @parent SettingLinkEquipment
*
* @param noOrnament
* @desc Motion without ornaments.
* 装飾品なし時のモーション
* @default
* @parent SettingLinkEquipment
*/
// ----------------------------
/**
* 共通関数
* 概要:ツクールエディタのプラグインで設定した変数をやりとりする関数群
*/
// ----------------------------
function parseStrToBoolean(str) {
// 文字列を判定
return str == "true" ? true : false;
}
const L2DINstringifyReplacer = function (key, value) {
if (value === "null") return value;
try {
return JSON.parse(value);
} catch (e) {
return value;
}
};
//設定値がある場合にはそれは配列になる。
const L2DINextractmeta = function (data) {
const req = /<([^<>:]+)(:?)([^>]*)>/g;
data.meta = {};
for (var i = 0; i < 1000; i++) {
var match = req.exec(data.motiongroupnames);
if (!!match) {
if (match[2] === ":") {
data.meta[match[1]] = match[3].split(", ");
} else {
data.meta[match[1]] = true;
}
} else {
break;
}
}
};
const L2DINfindnameindex = function (name) {
return L2DINmodels.findIndex(function (data) {
return data.Modelname === name;
});
};
const L2DINgetmetaarray = function (data, tag) {
const meta = data.meta[tag];
if (!meta || meta === true) {
return [];
}
return meta;
};
const L2DINPP = PluginManager.parameters("Live2DInterfaceMZ");
const L2DINleft = Number(L2DINPP["left"]) || 0;
const L2DINmiddle = Number(L2DINPP["middle"]) || 0;
const L2DINright = Number(L2DINPP["right"]) || 0;
const L2DINvertical = Number(L2DINPP["vertical"]) || 0;
const L2DINscaleX = Number(L2DINPP["scale_V"]) / 100;
const L2DINscaleY = Number(L2DINPP["scale_H"]) / 100;
const L2DINincludesave = L2DINPP["includesave"] === "true";
const L2DINuseinbattle = L2DINPP["useinbattle"] === "true";
const L2DINuseLinkEquipment = L2DINPP["useLinkEquipment"] === "true";
const L2DINpictpriority = Number(L2DINPP["pictpriority"]) || 0;
//Array型、各要素はobject
const L2DINmodels = JSON.parse(JSON.stringify(L2DINPP["Modelcondition"], L2DINstringifyReplacer));
L2DINmodels.forEach(function (Ldata) {
L2DINextractmeta(Ldata);
});
//共通変数(Live2Dファイル拡張子、画面解像度)
const model3expend = ".model3.json";
const motion3expend = ".motion3.json";
const L2DINgrawidth = 816;
const L2DINgraheight = 640;
//再生速度
const L2DINPlaybackSpeed = Number(L2DINPP["playbackSpeed"]) / 10;
//重み調整
const AdjustWeight = Number(L2DINPP["AdjustWeight"]) / 10;
const ScaleGain = Number(L2DINPP["ScaleGain"]);
//-----------------------------------------------------------------------------
//MotionElement
//モーションのグループ、番号のまとまり
//Slip 2021/07/03
//-----------------------------------------------------------------------------
function MotionElement() {
this.number = -1;
this.groupName = "none";
this.Isloop = false;
}
// ----------------------------
/* クラスGame_Live2d
* 概要Live2Dモデルをツクール上で動作させるためのデータを持つクラス。
* 扱いはgame_xxxと同等($gameLive2dをインスタンスとして、メソッドを呼び出す)
*/
//----------------------------
var $gameLive2d = null;
function Game_Live2d() {
this.initialize.apply(this, arguments);
}
Game_Live2d.prototype.initialize = function () {
this.clear();
};
//マジックナンバーだと分かりにくいのでパラメータ設定のモデル名をkeyにする。
Game_Live2d.prototype.clear = function () {
var parameters = PluginManager.parameters("Live2DInterfaceMZ");
//エディタ(プラグインの設定)から取得する設定値
this._folder = {};
this._name = {};
this._model = {};
this._pos_left = Number(parameters["left"]);
this._pos_middle = Number(parameters["middle"]);
this._pos_right = Number(parameters["right"]);
this._pos_vertical = Number(parameters["vertical"]);
this._IsUpsidedown = parseStrToBoolean(parameters["upsidedown"]);
//コマンド経由の設定値(ここでは初期値を設定する)
this.visible = {}; //モデルの表示、非表示
this.pos_x = {}; //モデルのX位置
this.pos_y = {}; //モデルのY位置
this._targetX = {}; //モデルのX目標位置
this._targetY = {}; //モデルのY目標位置
this._duration = {}; //移動する時間
this._live2dmodelsaveonly = {}; //セーブ用データ
this.CBR_fadeMode = {}; //
this.CBR_fadeDuration = {}; //
this.CBR_DURATION = 5;
//モーション関係のデータ (モーション再生、セーブデータの保存、読み込みとして必要)
this.motionGroup = {};
this.motionNumber = {};
this.motionElements = {};
//モーションの強制実行フラグ
this.IsForcedExe_NextMotion = {};
//表情データ
this.expressionName = {};
//表情変更の強制実行フラグ
this.IsForcedExe_ChangeExpression = {};
this.motionLoop = {};
this.paraminitskip = {};
this.cloth_act = {};
this.bote_act = {};
this.scale = {}; //スケール
this.A = {};
this.R = {};
this.G = {};
this.B = {};
this._waitCount = 0;
//個々の上下反転フラグ全体のフラグ、または個々のフラグがtrueになっていると上下反転の表示
this.individual_upsidedown = {};
//装備品、衣装変更時に使用。装備なし時のモーション
this.linkEquip_None = {};
this.InitializeModelSetting();
};
Game_Live2d.prototype.CBR_getDuration = function () {
return this.CBR_DURATION;
};
//各モデル設定値の初期化
Game_Live2d.prototype.InitializeModelSetting = function () {
var parameters = PluginManager.parameters("Live2DInterfaceMZ");
var i = 1;
L2DINmodels.forEach(function (data) {
this._folder[i] = data.folderpath;
this._name[i] = data.Modelname;
var strCopy = data.folderpath.split("/");
this._model[i] = strCopy[strCopy.length - 2];
this.visible[i] = false;
this.scale[i] = Number(parameters["DefaultScale"]);
this.A[i] = 1.0;
this.R[i] = 1.0;
this.G[i] = 1.0;
this.B[i] = 1.0;
this._duration[i] = 0;
this.pos_x[i] = this._pos_middle;
this.pos_y[i] = this._pos_vertical;
this._live2dmodelsaveonly[this._name[i]] = {};
this.motionGroup[i] = "Idle";
this.motionNumber[i] = 1;
this.motionElements[i] = [];
this.IsForcedExe_NextMotion[i] = false;
this.expressionName[i] = "";
this.IsForcedExe_ChangeExpression[i] = false;
this.motionLoop[i] = false;
this.paraminitskip[i] = false;
this.cloth_act[i] = false;
this.bote_act[i] = false;
//個々の上下反転フラグ全体のフラグ、または個々のフラグがtrueになっていると上下反転の表示
this.individual_upsidedown[i] = data.individual_upsidedown;
//装備品、衣装変更時に使用。装備なし時のモーション
this.linkEquip_None[i] = {};
this.linkEquip_None[i][0] = data.noWeapon;
this.linkEquip_None[i][1] = data.noShield;
this.linkEquip_None[i][2] = data.noHead;
this.linkEquip_None[i][3] = data.noBody;
this.linkEquip_None[i][4] = data.noOrnament;
i++;
}, this);
this.MAXNUMBER = i - 1;
};
//セーブデータの設定値をモデルに反映
Game_Live2d.prototype.ReflectSavedataToModels = function () {
var i = 1;
L2DINmodels.forEach(function (data) {
var saveobj = this._live2dmodelsaveonly[data.Modelname];
if (saveobj.vis) {
this.visible[i] = saveobj.vis;
this.scale[i] = saveobj.scx;
this.pos_x[i] = saveobj.px;
this.pos_y[i] = saveobj.py;
$gameLive2d.motionGroup[i] = saveobj.motionGroup;
$gameLive2d.motionNumber[i] = saveobj.motionNumber;
$gameLive2d.motionLoop[i] = saveobj.motionLoop;
//モーションを強制実行する
$gameLive2d.IsForcedExe_NextMotion[i] = true;
//表情変更を強制実行する
$gameLive2d.IsForcedExe_ChangeExpression[i] = true;
$gameLive2d.motionElements[i].splice(0);
var motionElement = new MotionElement();
motionElement.groupName = saveobj.motionGroup;
motionElement.number = saveobj.motionNumber;
motionElement.Isloop = saveobj.motionLoop;
$gameLive2d.motionElements[i].push(motionElement);
$gameLive2d.paraminitskip[i] = saveobj.paraminitskip;
$gameLive2d.cloth_act[i] = saveobj.cloth_act;
$gameLive2d.bote_act[i] = saveobj.bote_act;
}
i++;
}, this);
};
//ニューゲームの時に前回セーブしたときの影響が残らないように
Game_Live2d.prototype.newgamefix = function () {
L2DINmodels.forEach(function (data) {
var name = data.Modelname;
var saveobj = this._live2dmodelsaveonly[name];
if (saveobj) {
saveobj.isneedrestore = false;
}
}, this);
this.InitializeModelSetting();
};
//モデルの全ての情報をセーブするわけではないことに注意。
Game_Live2d.prototype.Createsavemodel = function () {
var i = 1;
L2DINmodels.forEach(function (data) {
var name = data.Modelname;
var saveobj = this._live2dmodelsaveonly[name];
saveobj.isneedrestore = true;
saveobj.px = $gameLive2d.pos_x[i];
saveobj.py = $gameLive2d.pos_y[i];
saveobj.scx = $gameLive2d.scale[i];
saveobj.vis = $gameLive2d.visible[i];
saveobj.motionGroup = $gameLive2d.motionGroup[i];
saveobj.motionNumber = $gameLive2d.motionNumber[i];
saveobj.motionLoop = $gameLive2d.motionLoop[i];
saveobj.paraminitskip = $gameLive2d.paraminitskip[i];
saveobj.cloth_act = $gameLive2d.cloth_act[i];
saveobj.bote_act = $gameLive2d.bote_act[i];
i++;
}, this);
return this._live2dmodelsaveonly;
};
//loaderより先に実行されることに注意。
Game_Live2d.prototype.Restoresavemodel = function (saveobj) {
this._live2dmodelsaveonly = saveobj;
};
//各シーンのupdateで呼ぶ
Game_Live2d.prototype.live2dupdate = function () {
L2DINmodels.forEach(function (targetobj) {
var model = this._live2dmodel[targetobj.Modelname];
if (model !== null) {
this.live2dupdateMove(model);
}
}, this);
};
//Cubism4対応 Slip 2020/01/13
Game_Live2d.prototype.getTextureManager = function () {
return this._textureManager;
};
//各シーンのupdateで呼ぶ
Game_Live2d.prototype.live2dupdate = function () {
L2DINmodels.forEach(function (targetobj) {
var model_no = 1;
for (var number in $gameLive2d._name) {
if ($gameLive2d._name[number] == targetobj.Modelname) {
break;
}
model_no++;
}
var model = null;
if (model !== null) {
this.live2dupdateMove(model_no);
}
}, this);
};
Game_Live2d.prototype.wait = function (dur) {
this._waitCount = dur;
};
//移動する
Game_Live2d.prototype.live2dupdateMove = function (model_no) {
var d = $gameLive2d._duration[model_no];
if (d > 0) {
$gameLive2d.pos_x[model_no] = ($gameLive2d.pos_x[model_no] * (d - 1) + $gameLive2d._targetX[model_no]) / d;
$gameLive2d.pos_y[model_no] = ($gameLive2d.pos_y[model_no] * (d - 1) + $gameLive2d._targetY[model_no]) / d;
$gameLive2d._duration[model_no]--;
}
};
//内部のモーション名
Game_Live2d.prototype.InnerMotionName = function (name, group) {
const index = L2DINfindnameindex(name);
if (index >= 0) {
const innerMotionName = L2DINgetmetaarray(L2DINmodels[index], group);
return innerMotionName;
} else {
return null;
}
};
//-----------------------------------------------------------------------------
//Live2DManager
//会話上にLive2Dモデルを表示するクラス
// Slip 2016/12/25
//-----------------------------------------------------------------------------
function Live2DManager() {
this.initialize.apply(this, arguments);
}
var live2dmodel = {};
Live2DManager.initialize = function () {
for (var i = 1; i <= $gameLive2d.MAXNUMBER; i++) {
live2dmodel[i] = null;
}
};
Live2DManager.getNumberFromName = function (modelName) {
var gameLive2d_no = 1;
for (var number in $gameLive2d._name) {
if ($gameLive2d._name[number] == modelName) {
break;
}
gameLive2d_no++;
}
return gameLive2d_no;
};
//表示フラグ
Live2DManager.live2dVisible = function (model_no, flag) {
$gameLive2d.visible[model_no] = flag;
};
//モーション設定
Live2DManager.live2dMotion = function (model_no, motionGroup, motion_no, loop) {
$gameLive2d._lappLive2dManager._models.at(model_no - 1).changeMotion(motionGroup, motion_no - 1, loop);
//セーブデータ保存用
$gameLive2d.motionGroup[model_no] = motionGroup;
$gameLive2d.motionNumber[model_no] = motion_no;
$gameLive2d.motionLoop[model_no] = loop;
this.Modelparaminit(model_no);
};
//すべてのモデルの設定されたモーションを再生する(表示されたモーションのみ。セーブデータのロード用)
Live2DManager.PlayBackAllModel = function () {
for (var i = 1; i <= $gameLive2d.MAXNUMBER; i++) {
if ($gameLive2d.visible[i] == true) {
this.live2dMotion(i, $gameLive2d.motionGroup[i], $gameLive2d.motionNumber[i], $gameLive2d.motionLoop[i]);
}
}
};
//モーション再生
Live2DManager.live2dSequenceMotion = function (model_no, motions, loop) {
var count_inLoop = 1;
var motionNames = String(motions).split(",");
var count_Max = motionNames.length;
//スタックされたモーションがあるかもしれないので一掃する
$gameLive2d.motionElements[model_no].splice(0);
//強制実行
$gameLive2d.IsForcedExe_NextMotion[model_no] = true;
motionNames.forEach(function (motionName) {
var data = String(motionName).split("_");
var motionElement = new MotionElement();
motionElement.groupName = data[0];
motionElement.number = Number(data[1]) - 1;
if (count_Max == count_inLoop) {
motionElement.Isloop = loop;
//セーブデータ保存用
$gameLive2d.motionLoop[model_no] = loop;
} else {
motionElement.Isloop = false;
}
$gameLive2d.motionElements[model_no].push(motionElement);
//セーブデータ保存用
$gameLive2d.motionGroup[model_no] = data[0];
$gameLive2d.motionNumber[model_no] = Number(data[1]) - 1; //実際にあつかうモーションNoは-1されている
count_inLoop = count_inLoop + 1;
});
};
//表情設定
Live2DManager.live2dExpression = function (model_no, expressionName) {
//強制実行
$gameLive2d.IsForcedExe_ChangeExpression[model_no] = true;
$gameLive2d.expressionName[model_no] = expressionName;
};
//位置変更(移動可能)
Live2DManager.live2dSetPosition = function (model_no, x, y, dur, wait) {
if (dur > 0) {
$gameLive2d._targetX[model_no] = x;
$gameLive2d._targetY[model_no] = y;
} else {
$gameLive2d.pos_x[model_no] = x;
$gameLive2d.pos_y[model_no] = y;
}
$gameLive2d._duration[model_no] = dur;
if (wait) {
$gameLive2d._waitCount = dur;
}
};
//表示位置変更
Live2DManager.live2dSetPosition_X = function (model_no, pos_x) {
if (pos_x < 1) {
pos_x = 1;
} else if (pos_x > Graphics.width) {
pos_x = Graphics.width;
} else {
pos_x = pos_x;
}
$gameLive2d.pos_x[model_no] = pos_x;
};
//表示位置変更
Live2DManager.live2dSetPosition_Y = function (model_no, pos_y) {
if (pos_y < 1) {
pos_y = 1;
} else if (pos_y > Graphics.height) {
pos_y = Graphics.height;
} else {
pos_y = pos_y;
}
$gameLive2d.pos_y[model_no] = pos_y;
};
//倍率変更
Live2DManager.live2dSetScale = function (model_no, scale) {
$gameLive2d.scale[model_no] = scale;
};
//初期化スキップ
Live2DManager.live2dsetparaminitskip = function (model_no, flag) {
$gameLive2d.paraminitskip[model_no] = flag;
};
Live2DManager.live2dsetcloth_act = function (model_no, flag, actor) {
$gameLive2d.cloth_act[model_no] = actor;
};
Live2DManager.live2dsetbote_act = function (model_no, flag, actor) {
$gameLive2d.bote_act[model_no] = actor;
};
//グレースケール変更
Live2DManager.live2dSetGrayscale = function (model_no, grayscale) {
$gameLive2d.R[model_no] = grayscale;
$gameLive2d.G[model_no] = grayscale;
$gameLive2d.B[model_no] = grayscale;
};
//上下反転
Live2DManager.live2dDisplayDirection = function (flag) {
$gameLive2d._IsUpsidedown = flag;
};
//衣装変更
Live2DManager.live2dChangeCloth = function (model_no, Id) {
$gameLive2d._lappLive2dManager._models.at(model_no - 1).setClothMotion(Id);
};
//装備とモデルの連動
Live2DManager.live2dClothLinkEquipment = function () {
//衣装変更用
for (var i = 0; i < $gameParty._actors.length; i++) {
for (var number in $gameLive2d._name) {
if ($gameParty.members()[i]._name == $gameLive2d._name[number]) {
for (var j = 0; j < 5; j++) {
//装備スロット
if ($gameLive2d.linkEquip_None[number][j] != "") {
var index = $gameParty.members()[i]._equips[j]._itemId;
var cloth_name = null;
if ($dataArmors[index]) {
cloth_name = $dataArmors[index].name;
} else {
cloth_name = $gameLive2d.linkEquip_None[number][j];
}
var innerMotionName = null;
innerMotionName = $gameLive2d.InnerMotionName($gameLive2d._name[number], cloth_name);
var modelNo = Live2DManager.getNumberFromName($gameLive2d._name[number]);
$gameLive2d._lappLive2dManager._models.at(modelNo - 1).setClothMotion(innerMotionName);
}
}
}
}
}
};
// ----------------------------
// Sprite_Live2d
// ----------------------------
function Sprite_Live2d() {
this.initialize.apply(this, arguments);
}
Sprite_Live2d.prototype = Object.create(PIXI.Container.prototype);
Sprite_Live2d.prototype.constructor = Sprite_Live2d;
Sprite_Live2d.prototype.initialize = function () {
PIXI.Container.call(this);
this._model = null;
var filter = new PIXI.filters.OpacityFilter();
filter.uniforms.opa = 1.0;
this.filters = [filter];
this.CBR_kousoku = new Sprite();
this.CBR_kousoku.x = -300;
this.CBR_kousoku.y = -700;
this.addChild(this.CBR_kousoku);
};
Sprite_Live2d.prototype.update = function () {
if (this._model) {
// live2dのスピード
this._model.update(16);
}
};
Sprite_Live2d.prototype.showImg = function (img) {
this._model.visible = false;
this.CBR_kousoku.bitmap = ImageManager.loadPicture(img);
this.CBR_kousoku.visible = true;
};
Sprite_Live2d.prototype.hideImg = function () {
this.CBR_kousoku.visible = false;
this._model.visible = true;
};
Sprite_Live2d.prototype.loadModel = function (name) {
this.clear();
const option = { autoInteract: false, autoUpdate: false, motionPreload: PIXI.live2d.MotionPreloadStrategy.ALL };
PIXI.live2d.Live2DModel.from("./" + name, option)
.then((model) => {
if (!this._model) {
this._model = model;
this.addChild(model);
model.anchor.set(0.5, 0.5);
}
})
.catch((error) => {
console.error(error);
});
};
Sprite_Live2d.prototype.clear = function () {
if (this._model) {
this.removeChild(this._model);
this._model = null;
}
};
var CBR_forceShow = function (name) {
setTimeout(
function (name) {
var model_no = Live2DManager.getNumberFromName(name);
Live2DManager.live2dVisible(model_no, true);
},
0,
name
);
};
var CBR_forceHide = function (name) {
setTimeout(
function (name) {
var model_no = Live2DManager.getNumberFromName(name);
Live2DManager.live2dVisible(model_no, false);
},
0,
name
);
};
var CBR_forceShowHide = function (name1, name2) {
setTimeout(
function (name1, name2) {
var model_no = Live2DManager.getNumberFromName(name1);
Live2DManager.live2dVisible(model_no, true);
var model_no = Live2DManager.getNumberFromName(name2);
Live2DManager.live2dVisible(model_no, false);
},
0,
name1,
name2
);
};
(() => {
"use strict";
const Scene_Base_initialize = Scene_Base.prototype.initialize;
Scene_Base.prototype.initialize = function () {
Scene_Base_initialize.call(this);
this.CBR_live2D_list = [];
};
//---Scene_Baseの上書き---
//---シーン上にlive2dモデル用スプライトを作成する---
Scene_Base.prototype.createlive2d = function () {
this.live2dSprite = {};
for (var k = 0; k < this.CBR_live2D_list.length; k++) {
var i = this.CBR_live2D_list[k];
var fileFullPath = $gameLive2d._folder[i] + $gameLive2d._model[i] + ".model3.json";
this.live2dSprite[i] = new Sprite_Live2d();
this.live2dSprite[i].loadModel(fileFullPath);
this.live2dSprite[i].x = $gameLive2d.pos_x[i];
this.live2dSprite[i].y = $gameLive2d.pos_y[i];
this.live2dSprite[i].scale.set(0.2, 0.2);
//非表示で描画する
//this.live2dSprite[i].alpha = 0;
this.live2dSprite[i].visible = false;
SceneManager._scene._spriteset.addChildlive2d(this.live2dSprite[i]);
//セーブデータの設定値をモデルに反映
$gameLive2d.ReflectSavedataToModels();
}
if (L2DINuseLinkEquipment == true) {
Live2DManager.live2dClothLinkEquipment();
}
};
Scene_Base.prototype.resetLive2d = function (i, name) {
var fileFullPath = $gameLive2d._folder[i] + $gameLive2d._model[i] + ".model3.json";
this.live2dSprite[i].loadModel(fileFullPath);
var motionElement = new MotionElement();
motionElement.groupName = name;
motionElement.number = 0;
motionElement.Isloop = true;
//セーブデータ保存用
$gameLive2d.motionLoop[i] = true;
$gameLive2d.motionElements[i].push(motionElement);
//セーブデータの設定値をモデルに反映
$gameLive2d.ReflectSavedataToModels();
};
Scene_Base.prototype.updatelive2d = function () {
for (var k = 0; k < this.CBR_live2D_list.length; k++) {
var i = this.CBR_live2D_list[k];
//表示非表示の更新
this.live2dSprite[i].visible = $gameLive2d.visible[i];
if (this.live2dSprite[i]._model) {
//位置を更新する
$gameLive2d.live2dupdateMove(i);
this.live2dSprite[i].x = $gameLive2d.pos_x[i];
if (this.live2dSprite[i].x == 840) {
this.live2dSprite[i].y = 740;
} else {
this.live2dSprite[i].y = $gameLive2d.pos_y[i];
}
this.live2dSprite[i].scale.set(0.2 * $gameLive2d.scale[i], 0.2 * $gameLive2d.scale[i]);
if ($gameLive2d.CBR_fadeMode[i] == "hide") {
this.live2dSprite[i].filters[0].uniforms.opa = $gameLive2d.CBR_fadeDuration[i] / $gameLive2d.CBR_getDuration();
this.live2dSprite[i].x += 8 * ($gameLive2d.CBR_getDuration() - $gameLive2d.CBR_fadeDuration[i]);
if ($gameLive2d.CBR_fadeDuration[i] <= 0) {
$gameLive2d.CBR_fadeMode[i] = "";
$gameLive2d.visible[i] = false;
this.live2dSprite[i].filters[0].uniforms.opa = 1;
$gameLive2d.pos_x[i] = 300;
} else {
$gameLive2d.CBR_fadeDuration[i]--;
}
}
if ($gameLive2d.CBR_fadeMode[i] == "show") {
$gameLive2d.visible[i] = true;
this.live2dSprite[i].filters[0].uniforms.opa = 1 - $gameLive2d.CBR_fadeDuration[i] / $gameLive2d.CBR_getDuration();
this.live2dSprite[i].x -= 8 * $gameLive2d.CBR_fadeDuration[i];
if ($gameLive2d.CBR_fadeDuration[i] <= 0) {
$gameLive2d.CBR_fadeMode[i] = "";
this.live2dSprite[i].filters[0].uniforms.opa = 1;
} else {
$gameLive2d.CBR_fadeDuration[i]--;
}
}
if (this.live2dSprite[i]._model.internalModel) {
//モーションの開始条件は以下いずれかが満たされていること
//1:モーション終了している
//2:プラグインコマンドからの実行強制実行フラグtrue
if (this.live2dSprite[i]._model.internalModel.motionManager.isFinished() || $gameLive2d.IsForcedExe_NextMotion[i] == true) {
var motionElement = $gameLive2d.motionElements[i].shift();
if (motionElement) {
//初期化スキップモデルのモーションパラメータを0にする
if ($gameLive2d.paraminitskip[i]) {
this.live2dSprite[i]._model.internalModel.coreModel._parameterValues.fill(0);
}
// if ($gameLive2d.bote_act[i]) {
// var idx = 0;
// if ($gameLive2d.bote_act[i] == "sira") {
// idx = 204;
// // ボテ腹着衣2
// // ボテ腹裸3
// var flag = $gameVariables.value(idx);
// this.live2dSprite[i]._model.internalModel.coreModel._parameterValues[43] = flag ? 1 : 0;
// this.live2dSprite[i]._model.internalModel.coreModel._parameterValues[44] = flag ? 1 : 0;
// } else if ($gameLive2d.bote_act[i] == "yozu") {
// idx = 205;
// this.live2dSprite[i]._model.internalModel.coreModel._parameterValues[34] = flag ? 1 : 0;
// }
// }
this.live2dSprite[i]._model.internalModel.motionManager.stopAllMotions();
//エラー回避 2023/01/25 slip
if (
this.live2dSprite[i]._model.internalModel.motionManager.motionGroups[motionElement.groupName][
motionElement.number
] !== undefined
) {
//モーションのループ設定
this.live2dSprite[i]._model.internalModel.motionManager.motionGroups[motionElement.groupName][
motionElement.number
].setIsLoop(motionElement.Isloop);
}
// //モーションのループ設定
// if (this.live2dSprite[i]._model.internalModel.motionManager.motionGroups[motionElement.groupName][motionElement.number]) {
// this.live2dSprite[i]._model.internalModel.motionManager.motionGroups[motionElement.groupName][
// motionElement.number
// ].setIsLoop(motionElement.Isloop);
// }
this.live2dSprite[i]._model.motion(motionElement.groupName, motionElement.number, 3);
//強制実行フラグをオフ(デフォルトに戻す)
$gameLive2d.IsForcedExe_NextMotion[i] = false;
}
}
//表情変更
if ($gameLive2d.IsForcedExe_ChangeExpression[i] == true) {
var expressions = this.live2dSprite[i]._model.internalModel.settings.expressions;
var expressionId = 0;
//エラー回避 2023/01/25 slip
if (expressions !== undefined) {
for (var j = 0; j < expressions.length; j++) {
if (expressions[j].Name == $gameLive2d.expressionName[i]) {
expressionId = j;
break;
}
}
}
this.live2dSprite[i]._model.expression(expressionId);
//強制実行フラグをオフ(デフォルトに戻す)
$gameLive2d.IsForcedExe_ChangeExpression[i] = false;
}
if ($gameLive2d.cloth_act[i]) {
var idx = 0;
if ($gameLive2d.cloth_act[i] == "sira") {
idx = 237;
} else if ($gameLive2d.cloth_act[i] == "yozu") {
idx = 238;
}
// ONの場合裸
this.live2dSprite[i]._model.internalModel.coreModel._parameterValues[24] = $gameSwitches.value(idx) ? 1 : -1;
$gameLive2d.cloth_act[i] = false;
}
}
}
}
};
Spriteset_Base.prototype.addChildlive2d = function (Sprite) {
if (L2DINpictpriority >= 100) {
this.addChild(Sprite);
} else {
this._pictureContainer.addChildAt(Sprite, L2DINpictpriority);
}
};
Scene_Base.prototype.terminatelive2d = function () {
for (var i = 1; i <= $gameLive2d.MAXNUMBER; i++) {
//this.live2dSprite[i].clear();
}
};
const DataManager_createGameObjects = DataManager.createGameObjects;
DataManager.createGameObjects = function () {
DataManager_createGameObjects.call(this);
if ($gameLive2d == null) {
$gameLive2d = new Game_Live2d();
}
};
//Scene_Mapの上書き
/*
const Scene_Map_terminate = Scene_Map.prototype.terminate;
Scene_Map.prototype.terminate = function () {
this.terminatelive2d();
Scene_Map_terminate.call(this);
};
const Scene_Map_start = Scene_Map.prototype.start;
Scene_Map.prototype.start = function () {
Scene_Map_start.call(this);
this.createlive2d();
};
const Scene_Map_update = Scene_Map.prototype.update;
Scene_Map.prototype.update = function () {
Scene_Map_update.call(this);
this.updatelive2d();
};
*/
//---Live2dモデルの戦闘画面表示機能---
if (L2DINuseinbattle) {
Scene_Battle.prototype.istickerupd = function () {
return true;
};
const Battle_L2DINupdate = Scene_Battle.prototype.update;
Scene_Battle.prototype.update = function () {
Battle_L2DINupdate.call(this);
this.updatelive2d();
};
const Battle_L2DINterminate = Scene_Battle.prototype.terminate;
Scene_Battle.prototype.terminate = function () {
Battle_L2DINterminate.call(this);
this.terminatelive2d();
};
const Battle_L2DINcreateWindowLayer = Scene_Battle.prototype.createWindowLayer;
Scene_Battle.prototype.createWindowLayer = function () {
this.CBR_live2D_list = [1, 2, 3, 4, 5, 6, 7, 8, 9];
this.createlive2d();
Battle_L2DINcreateWindowLayer.call(this);
};
} else {
console.log("Live2d表示はマップシーンのみです。");
}
//---Live2dモデルの設定をセーブデータに含める機能---
if (L2DINincludesave) {
const L2DINmakeSaveContents = DataManager.makeSaveContents;
DataManager.makeSaveContents = function () {
const contents = L2DINmakeSaveContents.call(this);
contents.Live2d = $gameLive2d.Createsavemodel();
return contents;
};
const L2DINextractSaveContents = DataManager.extractSaveContents;
DataManager.extractSaveContents = function (contents) {
L2DINextractSaveContents.call(this, contents);
if (!!contents && !!contents.Live2d) {
$gameLive2d.Restoresavemodel(contents.Live2d);
}
};
const L2DINsetupNewGame = DataManager.setupNewGame;
DataManager.setupNewGame = function () {
L2DINsetupNewGame.call(this);
$gameLive2d.newgamefix();
};
} else {
console.log("Live2d表示はセーブ・ロードしません。");
}
//---プラグインコマンドの処理---
const Game_Interpreter_updateWaitCount = Game_Interpreter.prototype.updateWaitCount;
Game_Interpreter.prototype.updateWaitCount = function () {
if ($gameLive2d._waitCount > 0) {
$gameLive2d._waitCount--;
return true;
}
return Game_Interpreter_updateWaitCount.call(this);
};
// プラグインコマンド
const pluginName = "Live2DInterfaceMZ";
PluginManager.registerCommand(pluginName, "show", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dVisible(model_no, true);
});
PluginManager.registerCommand(pluginName, "hide", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dVisible(model_no, false);
});
PluginManager.registerCommand(pluginName, "motion", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
var loop = false;
if (args.loop == "false") {
loop = false;
} else {
loop = true;
}
var innerMotionName = $gameLive2d.InnerMotionName(args.modelName, args.motionName);
Live2DManager.live2dSequenceMotion(model_no, innerMotionName, loop);
});
//表情変更
PluginManager.registerCommand(pluginName, "expression", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dExpression(model_no, args.expressionName);
});
//位置変更
//左
PluginManager.registerCommand(pluginName, "left", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dSetPosition_X(model_no, $gameLive2d._pos_left);
});
//真ん中
PluginManager.registerCommand(pluginName, "middle", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dSetPosition_X(model_no, $gameLive2d._pos_middle);
});
//右
PluginManager.registerCommand(pluginName, "right", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dSetPosition_X(model_no, $gameLive2d._pos_right);
});
//位置移動
PluginManager.registerCommand(pluginName, "pos", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
const x = Number(args.x) || 0;
const y = Number(args.y) || 0;
const dur = Number(args.dur) || 0;
var wait = args.wait;
Live2DManager.live2dSetPosition(model_no, x, y, dur, wait);
});
//大きさ変更
PluginManager.registerCommand(pluginName, "scale", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dSetScale(model_no, args.scale);
});
//初期化スキップ(強制モーション初期化)
PluginManager.registerCommand(pluginName, "paraminitskip", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dsetparaminitskip(model_no, args.IsInit);
});
//初期化スキップ(強制モーション初期化)
PluginManager.registerCommand(pluginName, "cloth_act", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dsetcloth_act(model_no, args.IsInit, args.actor);
});
//初期化スキップ(強制モーション初期化)
PluginManager.registerCommand(pluginName, "bote_act", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
Live2DManager.live2dsetbote_act(model_no, args.IsInit, args.actor);
});
//以下は実装するか検討中 slip 2021/07/14
PluginManager.registerCommand(pluginName, "set", (args) => {
var model_no = Live2DManager.getNumberFromName(args.modelName);
switch (args[1]) {
case "expression":
case "表情":
Live2DManager.live2dExpression(model_no, args[2]);
break;
case "grayscale":
case "グレースケール":
Live2DManager.live2dSetGrayscale(model_no, args[2]);
break;
case "衣装変更":
case "changecloth":
Live2DManager.live2dChangeCloth(model_no, args[2]);
}
});
})();
//live2d用半透明フィルター
PIXI.filters.OpacityFilter = function () {
var fragmentSrc = [
"precision lowp float;",
"uniform sampler2D uSampler;",
"varying vec2 vTextureCoord;",
"uniform float opa;",
"vec2 mapCoord( vec2 coord ){",
"return coord;",
"}",
"void main (void) {",
"vec2 coord = mapCoord(vTextureCoord);",
"gl_FragColor = texture2D(uSampler, coord );",
"gl_FragColor = vec4(gl_FragColor.r, gl_FragColor.g, gl_FragColor.b, gl_FragColor.a * opa);",
"}"
];
PIXI.Filter.call(
this,
null, // vertex shader
fragmentSrc.join("\n"), // fragment shader
{ opa: 0.0 } // uniforms
);
};
PIXI.filters.OpacityFilter.prototype = Object.create(PIXI.Filter.prototype);
PIXI.filters.OpacityFilter.prototype.constructor = PIXI.filters.OpacityFilter;