//=============================================================================
// villaA_SuctionHoleFilter.js
// Copyright (c) 2024- 村人Ａ
//=============================================================================
/*:
 * @target MZ
 * @plugindesc マップ画面に吸い込まれるような効果を付与するフィルターを適用します。
 * @author 村人Ａ
 *
 * @command switchFilter
 * @text フィルターのON/OFF
 * @desc 吸い込みホール状のフィルターを適用開始します。
 *
 * @command fadeoutFilter
 * @text フィルターを終わる
 * @desc 吸い込みホールフィルターを徐々に収束させ、自然な形で終了します。
 *
 * @help
 * ============================================================================
 * バージョン管理
 * ============================================================================
 * 24/12/10 ver 1.0 リリース
 *
 * ============================================================================
 * 概要
 * ============================================================================
 * このプラグインは、マップ画面に「吸い込まれるような」エフェクトを与える
 * フィルターを適用します。フィルターをONにすると、画面が中心へ引き込まれる
 * ようなビジュアル効果が現れ、不思議な空間や異世界転移などの演出に
 * 用いることができます。
 *
 * fadeoutFilterコマンドを使用することで、ゆるやかに効果を収束させ、
 * スムーズに元の状態へ戻すことができます。
 *
 * ============================================================================
 * プラグインコマンド
 * ============================================================================
 * ### フィルターのON/OFF (switchFilter)
 * 吸い込みホールのようなフィルターを適用開始します。
 * 実行後、マップ上で画面が中心へ引き寄せられるような効果が発生します。
 *
 * ### フィルターを終わる (fadeoutFilter)
 * 適用中の吸い込みホールフィルターを自然に収束させ、徐々に元の状態に戻します。
 *
 * ============================================================================
 * 使い方
 * ============================================================================
 * 1. **プラグインの導入**
 *    プラグインマネージャーで「villaA_SuctionHoleFilter.js」を有効化してください。
 *
 * 2. **フィルターの適用**
 *    イベントコマンド「プラグインコマンド」から「フィルターのON/OFF」を実行すると、
 *    マップ画面が吸い込まれるような効果が付与されます。
 *
 * 3. **フィルターのフェードアウト**
 *    同じく「フィルターを終わる」を実行すると、効果が徐々に弱まり、
 *    自然にフィルターが解除されます。
 *
 * 例:
 * ```
 * ◆プラグインコマンド：villaA_SuctionHoleFilter, フィルターのON/OFF
 * （マップが吸い込まれるような視覚効果が発生）
 *
 * --- イベント進行後 ---
 *
 * ◆プラグインコマンド：villaA_SuctionHoleFilter, フィルターを終わる
 * （徐々に効果が弱まり、元に戻る）
 * ```
 *
 * ============================================================================
 * 注意事項
 * ============================================================================
 * - フィルター適用中は描画負荷が増える可能性があります。
 * - 他のフィルターやエフェクトプラグインと併用する場合は、
 *   動作確認を行ってください。
 *
 * ============================================================================
 * 不具合報告
 * ============================================================================
 * 不具合はXやメールで報告してください。
 * Xアカウント：＠rpgmaker_villaA
 * メール：villaa.contact＠gmail.com
 *
 */

{
	'use strict';
	
	const pluginName = "villaA_SuctionHoleFilter";
    const param      = PluginManager.parameters(pluginName);
	
	//-----------------------------------------------------------------------------
	// SuctionHoleFilter
	//
	
	function SuctionHoleFilter() {
		this.initialize(...arguments);
	}

	SuctionHoleFilter.prototype = Object.create(PIXI.Filter.prototype);
	SuctionHoleFilter.prototype.constructor = SuctionHoleFilter;

	SuctionHoleFilter.prototype.initialize = function() {
		PIXI.Filter.call(this, null, this._fragmentSrc());
		this.isFadeout = false;
		this.reset();
	};
	
	SuctionHoleFilter.prototype.reset = function() {
		this.uniforms.iTime = 0.0;
	};

	SuctionHoleFilter.prototype.fadeout = function() {
		this.uniforms.iTime = 4;
		this.isFadeout = true;
	};

	SuctionHoleFilter.prototype.updateTime = function() {
		this.uniforms.iTime += this.isFadeout ? -0.02 : 0.02;
		$gameSystem.switchSuctionHoleFiter = this.uniforms.iTime;
		if (this.isFadeout && this.uniforms.iTime <= 0.0) {
			this.uniforms.iTime = 0.0;
			if (SceneManager._scene && SceneManager._scene.suctionHoleFilter) {
				SceneManager._scene.removeSuctionHoleFilter();
			}
		}
	};

	SuctionHoleFilter.prototype._fragmentSrc=function(){let src="varying vec2 vTextureCoord;uniform float iTime;uniform sampler2D uSampler;mat2 aBcD(float eFgH){return mat2(cos(eFgH),-sin(eFgH),sin(eFgH),cos(eFgH));}void main(){vec2 mNoP=gl_FragCoord.xy/vec2(816.0,624.0);vec2 qRsT=mNoP;vec4 uVwX=texture2D(uSampler,qRsT);vec4 yZaB=vec4(0.0);float cDeF=0.7;for(float gHiJ=0.0;gHiJ<9.0;gHiJ++){vec2 kLmN=mNoP;kLmN-=0.5;float oPqR=min(90.0,iTime*10.0);float sTuV=mod(max(0.0,iTime*oPqR-gHiJ*10.0),oPqR);kLmN=aBcD(radians(sTuV))*kLmN;kLmN*=max(0.0,1.0+sTuV*0.01);kLmN+=0.5;vec4 wXyZ=texture2D(uSampler,kLmN);wXyZ.a*=cDeF;yZaB=mix(yZaB,wXyZ*4.0,wXyZ.a);cDeF*=0.8;}yZaB*=min(1.0,iTime);gl_FragColor=mix(uVwX,yZaB,0.5)*0.7*(uVwX+0.5);}";return src;};

	//-----------------------------------------------------------------------------
	// PluginManager
	//
	
	PluginManager.registerCommand(pluginName, "switchFilter", args => {
		$gameSystem.switchSuctionHoleFiter = 0;
		SceneManager._scene.setSuctionHoleFilterToSpriteset();
	});
	
	PluginManager.registerCommand(pluginName, "fadeoutFilter", args => {
		SceneManager._scene.suctionHoleFilter.fadeout();
	});
	
	//-----------------------------------------------------------------------------
	// PluginManager
	//
	
	const _alias_Game_System_initialize = Game_System.prototype.initialize;
	Game_System.prototype.initialize = function() {
		_alias_Game_System_initialize.call(this)
		this.switchSuctionHoleFiter = -1;
	};

	//-----------------------------------------------------------------------------
	// Scene_Map
	//
	
	const _alias_Scene_Map_createSpriteset = Scene_Map.prototype.createSpriteset;
	Scene_Map.prototype.createSpriteset = function() {
		_alias_Scene_Map_createSpriteset.call(this)
		if(!this._spriteset.filters){
			this._spriteset.filters = [];
		}
		if($gameSystem.switchSuctionHoleFiter >= 0){
			this.setSuctionHoleFilterToSpriteset()
		}
	};
	
	Scene_Map.prototype.setSuctionHoleFilterToSpriteset = function() {
		if(this.suctionHoleFilter){return}
		this.suctionHoleFilter = new SuctionHoleFilter();
		this.suctionHoleFilter.uniforms.iTime = $gameSystem.switchSuctionHoleFiter;
		this._spriteset.filters.push(this.suctionHoleFilter)
	};
	
	Scene_Map.prototype.removeSuctionHoleFilter = function() {
		if (this.suctionHoleFilter) {
			this._spriteset.filters = this._spriteset.filters.filter(filter => filter !== this.suctionHoleFilter);
			this.suctionHoleFilter = null;
			$gameSystem.switchSuctionHoleFiter = -1;
		};
	};

	const _alias_Scene_Map_update = Scene_Map.prototype.update;
	Scene_Map.prototype.update = function() {
		_alias_Scene_Map_update.call(this)
		if(this.suctionHoleFilter){this.suctionHoleFilter.updateTime()}
	};
};
































