//=============================================================================
// RPG Maker MZ - 完全版Live2Dプラグインコマンド
//=============================================================================

/*:ja
 * @target MZ
 * @plugindesc Live2D機能のための完全版プラグインコマンドセット
 * @author えむうん
 * @base PictureLive2D
 * @orderAfter PictureLive2D
 *
 * @command setModel
 * @text Live2Dモデルの設定
 * @desc ピクチャにLive2Dモデルを設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルを設定するピクチャのID
 *
 * @arg modelName
 * @type string
 * @text モデル名
 * @desc 設定するLive2Dモデルの名前
 *
 * @command setAnimation
 * @text アニメーションの設定
 * @desc Live2Dモデルにアニメーションを設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg index
 * @type number
 * @text アニメーションインデックス
 * @desc アニメーショントラックのインデックス
 *
 * @arg animationNames
 * @type string
 * @text アニメーション名
 * @desc 設定するアニメーションの名前（カンマ区切りで複数指定可能）
 *
 * @arg order
 * @type select
 * @option 順次
 * @value sequential
 * @option ランダム
 * @value random
 * @option シャッフル
 * @value shuffle
 * @text 再生順序
 * @desc アニメーションの再生順序
 * @default sequential
 *
 * @arg continuance
 * @type select
 * @option 継続
 * @value continue
 * @option 1回のみ
 * @value none
 * @option リセット
 * @value reset
 * @text 継続オプション
 * @desc アニメーションの継続方法
 * @default continue
 *
 * @arg interrupt
 * @type boolean
 * @text 割り込み
 * @desc 現在のアニメーションを中断して新しいアニメーションを開始するかどうか
 * @default true
 *
 * @command clearAnimation
 * @text アニメーションのクリア
 * @desc 指定したインデックスのアニメーションをクリアします。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg index
 * @type number
 * @text アニメーションインデックス
 * @desc クリアするアニメーショントラックのインデックス
 *
 * @arg mixTime
 * @type number
 * @text ミックス時間
 * @desc アニメーションをクリアする際のミックス時間（秒）
 * @default 0
 *
 * @command setExpression
 * @text 表情の設定
 * @desc Live2Dモデルに表情を設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg expressionName
 * @type string
 * @text 表情名
 * @desc 設定する表情の名前
 *
 * @command clearExpression
 * @text 表情のクリア
 * @desc 現在の表情をクリアします。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @command setTimeScale
 * @text タイムスケールの設定
 * @desc アニメーションの再生速度を設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg scale
 * @type number
 * @text スケール
 * @desc アニメーションの再生速度（1.0が通常速度）
 * @decimals 2
 * @default 1.00
 *
 * @command setWeight
 * @text ウェイトの設定
 * @desc アニメーショントラックのウェイトを設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg index
 * @type number
 * @text アニメーションインデックス
 * @desc ウェイトを設定するアニメーショントラックのインデックス
 *
 * @arg weight
 * @type number
 * @text ウェイト
 * @desc 設定するウェイト値（0.0 ~ 1.0）
 * @decimals 2
 * @min 0
 * @max 1
 * @default 1.00
 *
 * @command setMix
 * @text ミックスの設定
 * @desc アニメーション間のミックス（補間）時間を設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg fromAnimation
 * @type string
 * @text 開始アニメーション
 * @desc ミックスの開始アニメーション名
 *
 * @arg toAnimation
 * @type string
 * @text 終了アニメーション
 * @desc ミックスの終了アニメーション名
 *
 * @arg duration
 * @type number
 * @text 持続時間
 * @desc ミックスの持続時間（秒）
 * @decimals 2
 * @default 1.00
 *
 * @command setAutoEyeBlink
 * @text 自動まばたきの設定
 * @desc 自動まばたき機能の有効/無効を設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg enabled
 * @type boolean
 * @text 有効化
 * @desc 自動まばたきを有効にするかどうか
 * @default true
 *
 * @command setColor
 * @text 色の設定
 * @desc Live2Dモデルの色を設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg r
 * @type number
 * @text 赤
 * @desc 赤色の値（0.0 ~ 1.0）
 * @decimals 2
 * @min 0
 * @max 1
 * @default 1.00
 *
 * @arg g
 * @type number
 * @text 緑
 * @desc 緑色の値（0.0 ~ 1.0）
 * @decimals 2
 * @min 0
 * @max 1
 * @default 1.00
 *
 * @arg b
 * @type number
 * @text 青
 * @desc 青色の値（0.0 ~ 1.0）
 * @decimals 2
 * @min 0
 * @max 1
 * @default 1.00
 *
 * @arg a
 * @type number
 * @text 不透明度
 * @desc 不透明度（0.0 ~ 1.0）
 * @decimals 2
 * @min 0
 * @max 1
 * @default 1.00
 *
 * @command setMosaic
 * @text モザイクの設定
 * @desc Live2Dモデルにモザイク効果を適用します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg size
 * @type number
 * @text サイズ
 * @desc モザイクのサイズ（1以上の値、1で効果なし）
 * @min 1
 * @default 1
 *
 * @command setOffset
 * @text オフセットの設定
 * @desc Live2Dモデルの表示位置をオフセットします。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg x
 * @type number
 * @text X座標
 * @desc X軸方向のオフセット値
 * @default 0
 *
 * @arg y
 * @type number
 * @text Y座標
 * @desc Y軸方向のオフセット値
 * @default 0
 *
 * @command setScale
 * @text スケールの設定
 * @desc Live2Dモデルの表示スケールを設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg scaleX
 * @type number
 * @text X方向スケール
 * @desc X軸方向のスケール値
 * @decimals 2
 * @default 1.00
 *
 * @arg scaleY
 * @type number
 * @text Y方向スケール
 * @desc Y軸方向のスケール値
 * @decimals 2
 * @default 1.00
 *
 * @command setVisible
 * @text 可視性の設定
 * @desc Live2Dモデルの可視性を設定します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg visible
 * @type boolean
 * @text 可視
 * @desc モデルを表示するかどうか
 * @default true
 *
 * @command resetParameters
 * @text パラメータのリセット
 * @desc 指定したパラメータをデフォルト値にリセットします。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg parameterIds
 * @type string
 * @text パラメータID
 * @desc リセットするパラメータのID（カンマ区切りで複数指定可能）
 *
 * @command playVoice
 * @text ボイス再生
 * @desc Live2Dモデルに関連付けられたボイスを再生し、再生時間を変数に格納します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @arg voicePath
 * @type string
 * @text ボイスファイルパス
 * @desc 再生するボイスファイルのパス
 *
 * @arg variableId
 * @type variable
 * @text 再生時間格納変数
 * @desc ボイスの再生時間を格納する変数のID（0で格納しない）
 * @default 0
 *
 * @command stopVoice
 * @text ボイス停止
 * @desc 現在再生中のボイスを停止します。
 *
 * @arg pictureId
 * @type number
 * @text ピクチャID
 * @desc Live2Dモデルが設定されているピクチャのID
 *
 * @help
 * このプラグインは、RPGツクールMZでLive2D機能を制御するための
 * 完全版プラグインコマンドセットを提供します。
 * PictureLive2D.jsプラグインが必要です。
 *
 * 主な機能：
 * 1. Live2Dモデルの設定
 * 2. アニメーションの制御（順序、継続、割り込み処理対応）
 * 3. 表情の設定
 * 4. パラメータの調整
 * 5. カラーやモザイク効果の適用
 * 6. 位置、スケール、可視性の制御
 * 7. ボイスの再生と停止
 *
 * 使用方法：
 * 1. PictureLive2D.jsをプラグインとして導入します。
 * 2. このプラグインをPictureLive2D.jsの後に配置します。
 * 3. イベントコマンドの「プラグインコマンド」から、
 *    各機能を呼び出して使用します。
 *
 * 注意事項：
 * - ピクチャIDは、「ピクチャの表示」で使用するIDと同じです。
 * - モデル名、アニメーション名、表情名は大文字小文字を区別します。
 */

(() => {
    'use strict';

    const pluginName = "PictureLive2D_Commands";

    const getGameLive2D = (pictureId) => {
        return $gameScreen.live2d(pictureId);
    };

    PluginManager.registerCommand(pluginName, "setModel", args => {
        const pictureId = Number(args.pictureId);
        const modelName = args.modelName;
        getGameLive2D(pictureId).setModel(modelName);
    });

    PluginManager.registerCommand(pluginName, "setAnimation", args => {
        const pictureId = Number(args.pictureId);
        const index = Number(args.index);
        const animationNames = args.animationNames.split(',').map(name => name.trim());
        const order = args.order;
        const continuance = args.continuance;
        const interrupt = args.interrupt === 'true';
        getGameLive2D(pictureId).setAnimation(index, animationNames, order, continuance, interrupt);
    });

    PluginManager.registerCommand(pluginName, "clearAnimation", args => {
        const pictureId = Number(args.pictureId);
        const index = Number(args.index);
        const mixTime = Number(args.mixTime);
        getGameLive2D(pictureId).clearAnimation(index, mixTime);
    });

    PluginManager.registerCommand(pluginName, "setExpression", args => {
        const pictureId = Number(args.pictureId);
        const expressionName = args.expressionName;
        getGameLive2D(pictureId).setExpression(expressionName);
    });

    PluginManager.registerCommand(pluginName, "clearExpression", args => {
        const pictureId = Number(args.pictureId);
        getGameLive2D(pictureId).clearExpression();
    });

    PluginManager.registerCommand(pluginName, "setTimeScale", args => {
        const pictureId = Number(args.pictureId);
        const scale = Number(args.scale);
        getGameLive2D(pictureId).setTimeScale(scale);
    });

    PluginManager.registerCommand(pluginName, "setWeight", args => {
        const pictureId = Number(args.pictureId);
        const index = Number(args.index);
        const weight = Number(args.weight);
        getGameLive2D(pictureId).setWeight(index, weight);
    });

    PluginManager.registerCommand(pluginName, "setMix", args => {
        const pictureId = Number(args.pictureId);
        const fromAnimation = args.fromAnimation;
        const toAnimation = args.toAnimation;
        const duration = Number(args.duration);
        getGameLive2D(pictureId).setMix(fromAnimation, toAnimation, duration);
    });

    PluginManager.registerCommand(pluginName, "setAutoEyeBlink", args => {
        const pictureId = Number(args.pictureId);
        const enabled = args.enabled === 'true';
        getGameLive2D(pictureId).setAutoEyeBlink(enabled);
    });

    PluginManager.registerCommand(pluginName, "setColor", args => {
        const pictureId = Number(args.pictureId);
        const r = Number(args.r);
        const g = Number(args.g);
        const b = Number(args.b);
        const a = Number(args.a);
        getGameLive2D(pictureId).setColor(r, g, b, a);
    });

    PluginManager.registerCommand(pluginName, "setMosaic", args => {
        const pictureId = Number(args.pictureId);
        const size = Number(args.size);
        getGameLive2D(pictureId).setMosaic(size);
    });

    PluginManager.registerCommand(pluginName, "setOffset", args => {
        const pictureId = Number(args.pictureId);
        const x = Number(args.x);
        const y = Number(args.y);
        getGameLive2D(pictureId).setOffset(x, y);
    });

    PluginManager.registerCommand(pluginName, "setScale", args => {
        const pictureId = Number(args.pictureId);
        const scaleX = Number(args.scaleX);
        const scaleY = Number(args.scaleY);
        getGameLive2D(pictureId).setScale(scaleX, scaleY);
    });

    PluginManager.registerCommand(pluginName, "setVisible", args => {
        const pictureId = Number(args.pictureId);
        const visible = args.visible === 'true';
        getGameLive2D(pictureId).setVisible(visible);
    });

    PluginManager.registerCommand(pluginName, "resetParameters", args => {
        const pictureId = Number(args.pictureId);
        const parameterIds = args.parameterIds.split(',').map(id => id.trim());
        getGameLive2D(pictureId).resetParameters(...parameterIds);
    });

    PluginManager.registerCommand(pluginName, "playVoice", args => {
        const pictureId = Number(args.pictureId);
        const voicePath = args.voicePath;
        const variableId = Number(args.variableId);

        const live2d = getGameLive2D(pictureId);
        live2d.playVoice(voicePath);

        if (variableId > 0) {
            const fullPath = 'audio/' + voicePath + AudioManager.audioFileExt();
            const xhr = new XMLHttpRequest();
            xhr.open('GET', fullPath, true);
            xhr.responseType = 'arraybuffer';
            xhr.onload = function() {
                if (xhr.status === 200) {
                    const context = new (window.AudioContext || window.webkitAudioContext)();
                    context.decodeAudioData(xhr.response, function(buffer) {
                        const duration = Math.ceil(buffer.duration); // 切り上げを行う
                        $gameVariables.setValue(variableId, duration);
                        context.close();
                    });
                }
            };
            xhr.send();
        }
    });

    PluginManager.registerCommand(pluginName, "stopVoice", args => {
        const pictureId = Number(args.pictureId);
        getGameLive2D(pictureId).stopVoice();
    });
})();