Skip to content

Instantly share code, notes, and snippets.

@miahmie
Last active October 22, 2022 15:30
Show Gist options
  • Save miahmie/7ace95ff2e2c097c87080b9f06f5be64 to your computer and use it in GitHub Desktop.
Save miahmie/7ace95ff2e2c097c87080b9f06f5be64 to your computer and use it in GitHub Desktop.
KAG3に[animpause][animresume][animreset]タグを追加する

KAG3 [animpause], [animresume] タグ追加スクリプト

概要

[animstart]を一時停止・再開するためのタグを追加するKAG改造スクリプトです。

[animstart] タグの機能/動作を追加する拡張するオプションもあります。

animstartの拡張は下記の通りです。

  • 対象のレイヤが無い/asdファイルが無い/asdのtargetジャンプ先が無い場合に無視するようになります
  • 対象レイヤがvisible時にのみanimstartを有効にするifvisibleオプションが追加されます

使い方

AfterInit.tjs に配置してください。 タグの説明はコメントを参照してください。

[animstart]の拡張を無効にしたい場合は @if (1) の部分を @if (0) にしてください。

その他

セーブロードに関しては特に問題ないと思われますが,あまりテストされていません。

AnimationLayerを改造する系のプラグインとの相性問題がある可能性があります。

特に [animstart] タグを改造するプラグインとは相入れない実装になっているので注意してください。 バッティングを回避するには [animstart] タグの拡張を無効にしてください

このスクリプトの利用・改造等は特に制限は設けませんのでご自由にお使いください。

/**
 * KAG3 の [animstart] タグに一時停止・再開機能を追加する
 * 使い方: このスクリプトを AfterInit.tjs に配置
 * 
 * animstartで再生中のアニメを一時停止する
 * [animpause   {page=ページ} layer=対象レイヤ seg=セグメント target=*停止状態ラベル]
 * ※ target=を指定するとそのラベルに対して [animstart] する(口パクの口を閉じるようなケースで利用)
 *    target=を指定しない場合はanimstop処理が行われてアニメが停止する
 *
 * animpauseで停止したアニメーションを再開する
 * [animresume {page=ページ} layer=対象レイヤ seg=セグメント]
 * 
 * animpauseタグの一時停止情報を消去する(resume情報が不要になった時)
 * [animreset]
 */

// タグハンドラの追加(上書き)
with (kag.tagHandlers)
{
@if (1) // [QuickHack] animstartタグ拡張を有効にする場合はここを 1 にする(※animstart タグを改造するプラグインを使用中の場合は相性問題が発生する可能性があるので注意!!)
	// ・layer指定の対象が無かった場合にエラー落ちせずに無視する判定を追加
	// ・asdが無かったりtarget先が無い場合にエラー落ちを防ぐ機能を追加
	// ・対象レイヤがvisible時にのみanimstartを有効にするifvisibleオプションを追加
	.animstart = function(elm) {
		updateBeforeCh = 1;
		var lay = getLayerFromElm(elm);
		if (lay) with (lay) {
			if (elm.ifvisible && !.visible) return 0; // [追加] ifvisibleチェック
			.startAnim(elm) if IsAnimationLabelExists(elm);
		}
		return 0;
	} incontextof kag;
@endif

	.animpause = function (elm) {
		updateBeforeCh = 1;
		var target = getLayerFromElm(elm);
		if (target) ProcessAnimPause(true, flags, target, elm);
		return 0;
	} incontextof kag;

	.animresume = function (elm) {
		updateBeforeCh = 1;
		var target = getLayerFromElm(elm);
		if (target) ProcessAnimPause(false, flags, target, elm);
		return 0;
	} incontextof kag;

	.animreset = function (elm) {
		updateBeforeCh = 1;
		ProcessAnimPause(null, flags);
		return 0;
	} incontextof kag;
}

// [animpause,resume,reset]タグ処理本体
function ProcessAnimPause(mode, f, target, elm) {
	var base = "animpause";
	if (mode === null) {
		// animreset: 情報クリア
		if (f[base] !== void) delete f[base];
		return;
	}

	// 保存用ID
	var tag = "%s:%d".sprintf(elm.layer, +elm.seg);

	// 状態保存先辞書
	var map = f[base];
	if (map === void) {
		map = f[base] = %[];
	}

	if (mode) {
		// animpause: 一時停止
		var store = null, seg = target.Anim_segments[+elm.seg];
		if (seg) store = %[ target:seg.startLabel, storage:Storages.extractStorageName(target.Anim_storageName) ];
		map[tag] = store;
		if (elm.target != "" && IsAnimationLabelExists(elm)) {
			target.startAnim(elm); // 別のアニメを開始して停止とする
		} else {
			target.stopAnim(+elm.seg); // 完全に停止する
		}
	} else {
		// animresume: 再開
		var resume = map[tag];
		if (resume === void) {
			Debug.message("animresume: anim復帰用データがありません:"+tag);
		} else {
			if (resume) {
				// アニメーション画像が停止時と同じだったかどうかをチェック
				var current = Storages.extractStorageName(target.Anim_storageName);
				if (resume.storage == current) {
					target.startAnim(%[ seg:elm.seg, target:resume.target ]);
				} else {
					Debug.message("animresume: anim復帰できません(画像が違います):"+tag, resume.storage, current);
				}
			} else {
				// pause時に既に停止状態だった
				target.stopAnim(+elm.seg);
			}
			delete map[tag]; // 情報を消去
		}
	}
}

// アニメーションのラベル有無を先行チェックする関数
function IsAnimationLabelExists(elm) {
	var target = kag.getLayerFromElm(elm);
	if (target && target.Anim_storageName != "") {
		if (elm.target == "") return true; // ラベル指定なしは常にOK
		// 調査用KAGParser
		if (typeof kag.labelCheckParser == "undefined") {
			var p= kag.labelCheckParser = new KAGParser();
			p.debugLevel = tkdlNone;
			p.labelMap = %[];
			kag.add(p);
		}
		with (kag.labelCheckParser) {
			// 前に調査済みかどうか
			var asd = target.Anim_storageName;
			var map = .labelMap;
			var cache = map[asd + elm.target];
			if (cache !== void) return cache;

			// 調査する
			if (.curStorage != asd) {
				.clear();
				.loadScenario(asd);
			}
			var result = true;
			try {
				.goToLabel(elm.target);
			} catch {
				result = false;
			}

			// 次回以降のために調査結果を記録する
			map[asd + elm.target] = result;
			return result;
		}
	}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment