shiny-cuty-excel-chiffon/data/system/AnimationLayer.tjs
2024-10-22 11:38:49 -05:00

1274 lines
52 KiB
Text
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.

// AnimationLayer.tjs - アニメーションを行うレイヤ
// Copyright (C)2001-2006, W.Dee and contributors 改変・配布は自由です
/*
-- 2つのアニメーションの種類 ---------------------------------------------
 KAGにアニメーションをさせるためにはつの種類があります。
 一つは「セル画像」を用いるセルを基本としたアニメーションで、この場合、
「ベース画像」の上に「セル画像」の各部分を切り取って順次貼り付けるような感
じでアニメーションを行います。
 もう一つは、KAG 3.05 beta 3 から使用可能になった クリッピングを基本とした
アニメーション方法で、この場合はセル画像は必要ありません。
 image タグに clipleft, cliptop, clipwidth, clipheight の4つの属性があり
ますが、(概念的には)これを順次変えてやることで、大きな画像の一部分を順次表
示するようなアニメーションを行います。表示する画像を何枚も横に並べ、それを
順次表示するような用途に向いています。
 負荷はクリッピングを基本としたアニメーション方式のほうが軽いです。デモ
シーンにおいて、レイヤの全域を書き換えるようなアニメーションを行う場合はク
リッピング方式のアニメーションのほうが良いでしょう。
 逆に、目パチ、口パクのような用途にはセル方式のアニメーションの方が小回り
が利いて使いやすいでしょう。
-- セル方式のアニメーションの記述の仕方 -----------------------------------
 まず、アニメーションを行わせるためには、「ベース画像」と「セル画像」が必
要になります。ベース画像はアニメーションの下地となる画像です。セル画像はア
ニメーションの「部品」が並べてある画像です。ベース画像の上にアニメーション
画像を部分的にコピーして重ねていくという方法を用います。
 ベース画像は image タグで読み込まれます (ここで用いるベースとは、KAGの背
景レイヤの base とは違う意味です )。セル画像は、アニメーション定義ファイル
内の loadcell タグで読み込みます。
 アニメーション定義ファイルは、ベース画像とファイルが同じで、拡張子が asd
のテキストファイルです。
 アニメーション定義ファイルは KAG の文法で記述しますが、タグ体系は KAG の
ものとは異なります。
 アニメーションセグメントを用いない、簡単なアニメーションならば、KAG の
System フォルダにある LineBreak や PageBreak が参考になると思います。
 アニメーションセグメントを用いたサンプルは現在の所、吉里吉里ソースの中の
environ/win32/kag3/scenario/animtest.ks にあります。
-- セグメント -------------------------------------------------------------
 セグメントは、一組のベース画像、セル画像、asdファイルで、複数のアニメー
ションを同時進行させるための仕組みです。
 セグメントにはレイヤごとに 0 番から始まる番号がついています。
 セグメント 0 は特殊なセグメントでデフォルトセグメントと呼ばれ、画像の読
み込みとともに実行が自動的に始まるセグメントです。system フォルダにある
LineBreak や PageBreak はこのデフォルトセグメントのみを使用しています。簡
単なアニメーションならばこれだけで十分だと思います。
 口パクや目パチなどを一つの画像で行いたい場合、複数のセグメントを扱わなけ
ればなりません。たとえば、目パチはデフォルトセグメントで常時アニメーション
させておき、口パクはシナリオの制御によって開始させたり、停止させたりする、
という用途です。
 セグメントに対するアニメーションのスタートは KAG の通常のシナリオの
animstart で行います。animstart は任意の ( デフォルトセグメント以外の ) セ
グメントでアニメーションを開始します。
 animstart タグの loop 属性が true のとき、このアニメーションはループして
いないといけません。自動的にループするわけではないので、ループするように記
述しなければなりません。
 ループしていなくてもエラーになるわけではありませんが、栞を保存して読み込
んだときに正しく画像が再現されない可能性があります。
また、栞が読み込まれるときは、loop=true を指定した場合のみにアニメーション
が再開されますが、かならず animstart で指定したasdファイルのラベルの最初か
ら実行が始まります。
 loop=false の時は、アニメーションはしますが、最終的に s タグで停止しなけ
ればなりません。また、[s] タグで停止したときには、ベース画像と同じ状態に戻っ
てなければなりません。単発のアニメーションを行わせたいときはこれを使います。
 animstop はアニメーションを停止させますが、停止を待ちません。実際はアニメー
ションが停止するためには @home タグを通過する必要があります。
 wa は任意のセグメントのアニメーションの終了を待ちます。デフォルトセグメン
トのアニメーションもまつことができます。animstart で loop=falseを指定したと
きや、animstop でアニメーションを停止させた時のみ有効です。他の場合で wa を
指定した場合は永遠に待つことになってしまいます。
 栞に保存される情報は、アニメーションがどのセグメントでどの開始ラベルから
始まったかという情報のみで、どのコマ位置まで進んでいるか、は記録されません。
 また、ループ中のアニメーションのみが、栞を読み込んだときにアニメーション
が再開されます。
-- クリッピング方式のアニメーションの記述の仕方 ---------------------------
 クリッピング方式でアニメーションを行う場合は、セル方式で行うときと異なり、
コマ画像が横並びになった画像を一枚用意します。
 たとえば、320x240 の画面で8枚の画像でアニメーションを行うならば、
2560×240 の画像を用意します ( 2560 = 320 * 8 )。
 画像を読み込むときは、最初のコマが表示されるように image タグを記述します。
 たとえば、
@image storage=anim page=fore layer=0 mode=rect clipleft=0 cliptop=0 clipwidth=320 clipheight=240
 となります。
 asd ファイルには、横に並んだ各コマ画像が順次表示されるように記述します。
セル画像は用いないので、loadcell タグを記述する必要はありません。
 たとえば、
@wait time=80
@clip left=320 top=0
@wait time=80
@clip left=640 top=0
@wait time=80
@clip left=960 top=0
@wait time=80
@clip left=1280 top=0
@wait time=80
@clip left=1600 top=0
@wait time=80
@clip left=1920 top=0
@wait time=80
@clip left=2240 top=0
@wait time=80
@s
 見てお気づきかとは思いますが、実際は横に並んでいる必要はありません。
 縦に並んでいても良いですが、png などで圧縮するときは横並びになっていた方
が高い圧縮率を得られます。
 クリッピング方式のアニメーションでは、栞には、そのレイヤがどのようにアニ
メーションを行っていたかの情報が保存されません。次の「栞を保存可能なラベル」
を通過するまでには、そのレイヤに別の画像を読み込むなどして、クリッピング方
式のアニメーションの情報を無効にしてください。
-- asdファイル中タグの説明 ------------------------------------------------
■ loadcell
・属性
storage (省略可) 読み込むセル画像ファイル名を指定します
・説明
 このタグはセル方式のアニメーションを行うときのみに使用します。
 loadcell タグはアニメーションのセル画像を読み込みます。セル画像を読み込ま
なければアニメーションができないので、asd ファイルの先頭には必ず記述します。
storage 属性が省略された場合は、ベース画像のファイル名に _a を付加した画像
が読み込まれます。
 asd ファイルの先頭に記述しさえすれば OK で、セグメントの開始ラベルの次に
記述する必要はありません。
■ loop
・属性
(なし)
・説明
 このタグはセル方式のアニメーションを行うときのみに使用します。
 loop タグは、データがループを行うことを宣言するためのタグです。
 このタグを宣言したからと言って自動的にデータがループするわけではありませ
ん。ループするように記述してください。
 このタグは、各セグメントでのループの開始を行う場合の、セグメントの入り口
のラベルの次あたりに記述してください。最初のデフォルトセグメントの場合は
loadcell の次あたりで OK です。
■ copy
・属性
dx 転送先x座標
dy 転送先y座標
sx 転送元x座標
sy 転送元y座標
sw 幅
sh 高さ
・説明
 このタグはセル方式のアニメーションを行うときのみに使用します。
 セル画像からベース画像にコピーを行います。
■ wait
・属性
time 待ち時間(ms)
・説明
 指定時間ウェイトをとります。
 通常は、copy タグと wait タグの繰り返しになります。
■ jump, if/endif, eval, iscript/endscript
 KAG のシナリオと同様です。
 ただし、複数が並列して実行される物なので、変数を操作する場合は使用する変
数が重ならないようにするなど、注意してください。
■ s
・属性
(なし)
・説明
 通常の KAG と同じように、そこで実行を停止します。
 アニメーションがループしない場合は、loop タグを書かずに、このタグで
停止させてください。
 画像が読み込まれた時点ではアニメーションをしたくないのならば、loadcell タ
グの直後に s タグを書いて停止させてください。
■ home
・属性
(なし)
・説明
 このタグはセル方式のアニメーションを行うときのみに使用します。
 animstop タグを指定した場合に停止する場所です。これを書かないと animstop
では停止できません。animstop タグを使う場合は、ループの途中に必ず一カ所以上
記述してください。
■ clip
・属性
left クリッピングを行う左端位置
top クリッピングを行う上端位置
 このタグはクリッピング方式のアニメーションを行うときのみに使用します。
 image タグにおける clipleft と cliptop 属性の値の効果と同じで、クリッピン
グを行う位置を指定します。
 クリッピングの幅と高さは変更できませんので、image タグで指定した幅と高さ
を変えることはできません。
*/
class AnimationConductor extends BaseConductor
{
var owner;
var number; // このコンダクタの番号
var looping = false;
var startLabel = "";
var stopping = false; // ストップを待っている状態か
var running = false; // 実行中か
//ryo--
var resetLabel = "";
function AnimationConductor(owner)
{
super.BaseConductor(); // スーパークラスのコンストラクタを呼ぶ
ignoreCR = true; // CR は無視
debugLevel = tkdlNone;
// debugLevel = tkdlVerbose;
this.owner = owner;
}
function finalize()
{
owner = void; // owner への参照を切る
super.finalize(...);
}
function onStop()
{
// 実行停止
var elm = %[];
elm.context = this;
owner.s(elm); // s タグを呼ぶ
}
function onTag(obj)
{
// タグが実行されるとき
var func = owner[obj.tagname];
if(func == void)
{
dm(Storages.extractFileName(curStorage) + " : 未知のタグ : " + obj.tagname);
return 0;
}
obj.context = this;
return func(obj);
}
function onScript(script, scriptname, lineofs)
{
// iscript が実行されるとき
try
{
Scripts.exec(script, scriptname, lineofs);
}
catch(e)
{
throw new Exception(scriptname + " の 行 " + lineofs + " から始まる"
" iscript ブロックでエラーが発生しました。"
"\n( 詳細はコンソールを参照してください )\n" + e.message);
}
return true;
}
function assign(src)
{
// src の状態をこのオブジェクトにコピー
super.assign(src);
looping = src.looping;
startLabel = src.startLabel;
stopping = src.stopping;
running = src.running;
}
}
class AnimationLayer extends KAGLayer
{
var Anim_cellLayer; // セルレイヤ
var Anim_segments = []; // セグメントごとのコンダクタ
var Anim_storageName; // アニメーションデータファイル名
var Anim_loadParams = void; // 読み込み時に指定されたパラメータ
var Anim_partialImageInfo = void; // 画像の部分追加読み込みのパラメータ
var Anim_interrupted = false;// 中断中か
var win;
var Anim_defaultFontInfo = %[];
function AnimationLayer(win, par)
{
// AnimationLayer コンストラクタ
super.KAGLayer(...); // スーパークラスのコンストラクタを呼ぶ
Anim_defaultFontInfo.face = font.face; // デフォルトのフォント
Anim_defaultFontInfo.height = font.height; // デフォルトのフォントサイズ
Anim_segments[0] = new AnimationConductor(this); // デフォルトのコンダクタ
Anim_segments[0].number = 0;
this.win = win;
}
function finalize()
{
clearAnim(); // アニメーション情報のクリア
invalidate Anim_segments[0]; // デフォルトのコンダクタを無効化
Anim_loadParams = void;
Anim_partialImageInfo = void;
super.finalize(...);
}
function clearImage(process = true)
{
// 表示を不可視(不可視にできれば)にし、
// レイヤをクリアする
// 必要に応じてオーバーライドすること
if(process)
{
visible = false;
setSize(32, 32);
setImageSize(32, 32);
face = dfAlpha;
fillRect(0, 0, 32, 32, 0);
// setSize(win.innerWidth, win.innerHeight);
// setImageSize(win.innerWidth, win.innerHeight);
left=0;
top=0;
face = dfAlpha;
fillRect(0, 0, win.innerWidth, win.innerHeight, 0);
type = ltOpaque;
face = dfAuto;
}
}
function freeImage()
{
// 画像を解放
clearAnim();
clearImage();
Anim_loadParams = void;
Anim_partialImageInfo = void;
}
function clearAnim()
{
// アニメーション情報のクリア
// アニメーションセグメントのクリア
// 各セグメント(デフォルトをのぞく)の削除
for(var i = Anim_segments.count -1; i>=1; i--)
{
var seg = Anim_segments[i];
invalidate Anim_segments[i] if seg !== void;
}
Anim_segments.count = 1;
// デフォルトのセグメントの停止
Anim_segments[0].stop();
// アニメーションセルレイヤの破棄
invalidate Anim_cellLayer if Anim_cellLayer !== void;
Anim_cellLayer = void;
}
function loadAnimInfo(segment, label)
{
// アニメーション情報を指定セグメントに読み込み、実行開始
// segment=セグメント番号 label=開始ラベル(空文字列ならば最初から)
// Anim_storageName に入っているファイル名のファイルを読み込む
if(Anim_storageName == '')
throw new Exception(
(Anim_loadParams !== void ? Anim_loadParams.storage + "に対する" : "") +
"アニメーション情報がありません");
var seg;
if(Anim_segments[segment] === void)
{
Anim_segments[segment] = seg = new AnimationConductor(this);
seg.number = segment;
// 新しいセグメント用にコンダクタを作成
}
else
{
// セグメントは停止
(seg = Anim_segments[segment]).stop();
}
seg.startLabel = label;
seg.stopping = false;
seg.running = true;
seg.clearCallStack();
seg.interrupted = Anim_interrupted;
seg.loadScenario(Anim_storageName);
if(label != '') seg.goToLabel(label);
seg.startProcess(true);
}
function startAnim(elm)
{
// elm に従ってアニメーションを開始する
loadAnimInfo(+elm.seg, elm.target);
}
function stopAnim(segment)
{
// segment で行われているアニメーションを停止する
var seg = Anim_segments[segment];
if(seg === void) return; // 停止できない
seg.stopping = true;
}
function canWaitAnimStop(segment)
{
// segment のアニメーションの終了を待てるかどうか
var seg = Anim_segments[segment];
if(seg === void) return false; // まてない
if(!seg.running) return false; // 実行中でないので待てない
if(seg.looping && !seg.stopping) return false; // ループ指定されていてかつストップ待ちでないのでまてない
return true;
}
function loadImages(elm)
{
// loadImages オーバーライド
// elm は読み込み情報
if(elm === void)
{
freeImage();
return;
}
Anim_loadParams = %[];
(Dictionary.assign incontextof Anim_loadParams)(elm);
// パラメータを待避
// アニメーション情報をクリア
clearAnim();
// 追加画像読み込みの情報をクリア
Anim_partialImageInfo = void;
// 画像を読み込む
var taginfo = super.loadImages(elm.storage, elm.key);
// 画像のタグ情報をデフォルト値として採用
if(taginfo)
{
(Dictionary.assign incontextof taginfo)(elm, false);
elm = taginfo;
}
// フリップ
var ud, lr;
if(elm.flipud !== void && +elm.flipud)
{
// 上下反転
flipUD();
ud = true;
}
else
{
ud = false;
}
if(elm.fliplr !== void && +elm.fliplr)
{
// 左右反転
flipLR();
lr = true;
}
else
{
lr = false;
}
// dm("(´・ω・`) storage : " + elm.storage + " , imageWidth : " + imageWidth);
// クリッピング
if(elm.clipleft !== void)
{
// クリッピングが指定されている
width = +elm.clipwidth;
height = +elm.clipheight;
var cl = elm.clipleft;
if(lr) cl = imageWidth - cl - width;
var ct = elm.cliptop;
if(ud) ct = imageHeight - ct - height;
imageLeft = -cl;
imageTop = -ct;
}
else
{
setSizeToImageSize();
}
// レイヤモード
{
var mode = ltAlpha;
if(elm.mode !== void)
{
var layertypeinfo = imageTagLayerType[elm.mode];
if(layertypeinfo !== void)
mode = layertypeinfo.type;
}
type = mode;
}
// 色補正
face = dfAuto;
applyColorCorrection(this, elm);
// 可視不可視、位置、不透明度、インデックス
if ( elm !== void && elm.pos !== void ) {
// ポジションに従って位置を決定
left= window.scPositionX[elm.pos] - width \ 2;
top = window.scHeight - height;
}
else
{
if(elm.left !== void) left = +elm.left;
if(elm.top !== void) top = +elm.top;
}
if(elm.visible !== void) visible = +elm.visible;
if(elm.opacity !== void) opacity = +elm.opacity;
absolute = +elm.index if elm.index !== void;
// アニメーション情報があれば、読み込む
Anim_storageName =
Storages.getPlacedPath(
Storages.chopStorageExt(elm.storage) + ".asd");
if(Anim_storageName != '')
{
// アニメーション情報があった!
// アニメーション情報をデフォルトのコンダクタに読み込む
loadAnimInfo(0, ''); // ついでにアニメーション開始(もし開始できれば)
}
}
function addPartialImageInfo(elm)
{
// elm を partialImageInfo に追加する
// Anim_partialImageInfo に情報を追加
if(Anim_partialImageInfo === void)
Anim_partialImageInfo = [];
var info = %[];
(Dictionary.assign incontextof info)(elm);
Anim_partialImageInfo.add(info);
}
function loadPartialImage(elm)
{
// 部分追加読み込みを行う
// この読み込みメソッドは レイヤそれ自体の
// 色調補正、フリップなどの設定に従う
// (従って pimage タグ自体には色調補正や
// フリップ関連の属性はない )
// pimage タグでは、時間をずらして順次部分画像を読み込み、
// アニメーションを行っていくような用途には向いていない
// ( そのような場合はアニメーション機能を使うべき )
if(elm.tagname === void) elm.tagname = "pimage";
// カラーキーの決定
var key;
if(elm.key !== void)
{
// key 指定がある
key = elm.key;
}
else
{
// key 指定がない
if(Anim_loadParams !== void)
key = Anim_loadParams.key; // loadParams の方の key を使う
else
key = void;
}
// 一時使用用のレイヤを得る
var temp = window.temporaryLayer;
// 一時レイヤに画像を読み込む
var taginfo = temp.loadImages(elm.storage, key);
// 画像のタグ情報をデフォルト値として採用
if(taginfo)
{
(Dictionary.assign incontextof taginfo)(elm, false);
elm = taginfo;
}
// レイヤモード
{
var mode = ltAlpha;
if(elm.mode !== void)
{
var layertypeinfo = imageTagLayerType[elm.mode];
if(layertypeinfo !== void)
mode = layertypeinfo.type;
}
temp.type = mode;
}
// 画像補整
var lr = false, ud = false;
if(Anim_loadParams !== void)
{
// 一時レイヤに対して色調補正
applyColorCorrection(temp, Anim_loadParams);
// フリップ
if(Anim_loadParams.flipud !== void && +Anim_loadParams.flipud)
{
// 上下反転
temp.flipUD();
ud = true;
}
if(Anim_loadParams.fliplr !== void && +Anim_loadParams.fliplr)
{
// 左右反転
temp.flipLR();
lr = true;
}
}
var dx = +elm.dx;
var dy = +elm.dy;
var sx = +elm.sx;
var sy = +elm.sy;
var sw = elm.sw === void ? temp.imageWidth : +elm.sw;
var sh = elm.sh === void ? temp.imageHeight : +elm.sh;
if(ud)
{
// 上下反転
dy = imageHeight - dy - sh;
sy = temp.imageHeight - sy - sh;
}
if(lr)
{
// 左右反転
dx = imageWidth - dx - sw;
sx = temp.imageWidth - sx - sw;
}
if(elm.mode == 'copy' || elm.mode == 'opaque')
{
// コピー
face = dfAlpha;
copyRect(dx, dy, temp, sx, sy, sw, sh);
}
else
{
// 重ね合わせ
var opa = elm.opacity === void ? 255 : +elm.opacity;
switch(elm.mode)
{
case '': // default
case 'pile':
case 'alpha':
holdAlpha = false;
face = dfAlpha;
break;
case 'addalpha':
holdAlpha = false;
face = dfAddAlpha;
break;
default:
holdAlpha = true;
face = dfOpaque;
break;
}
operateRect(dx, dy, temp, sx, sy, sw, sh, omAuto, opa);
face = dfAuto;
}
// Anim_partialImageInfo に情報を追加
addPartialImageInfo(elm);
return 0;
}
function drawReconstructibleText(elm)
{
// (ロード時に)再現可能な形式でテキストを描画する
// x, y = 座標
// text = 描画する文字列
// face = フォント, 省略時は デフォルトフォント名
// size = フォントサイズ, 省略時はデフォルトフォントサイズ
// color = 色 (デフォルト=0xffffff)
// italic = 斜体かどうか (デフォルト=false)
// shadow = 影つきかどうか (デフォルト=true)
// edge = 縁取りかどうか (デフォルト=false)
// shadowcolor = 影の色 (デフォルト=0)
// edgecolor = 縁取りの色 (デフォルト=0)
// bold = 太字にするかどうか (デフォルト=0)
// vertical = 縦書きかどうか (デフォルト=false)
// antialiased = アンチエイリアスするか (デフォルト=true)
// angle = 描画角度 (デフォルト=縦書きならば2700, そうでなければ0)
if(elm.tagname === void) elm.tagname = "ptext";
var vertical = elm.vertical === void ? false : +elm.vertical;
with(font)
{
var face = elm.face === void ? Anim_defaultFontInfo.face : elm.face;
if(vertical) face = '@' + face;
.face = face;
.height = elm.size === void ? Anim_defaultFontInfo.height : +elm.size;
.angle = elm.angle === void ? vertical ? 2700:0 : +elm.angle;
.italic = elm.italic === void ? false : +elm.italic;
.bold = elm.bold === void ? false: +elm.bold;
}
var edge = elm.edge === void ? false : +elm.edge;
var shadow = elm.shadow === void ? true : +elm.shadow;
var color = elm.color === void ? 0xffffff : +elm.color;
var antialiased = elm.antialiased === void ? true : +elm.antialiased;
face = dfAuto;
var x = +elm.x;
var y = +elm.y;
if(edge)
{
var bcolor = elm.edgecolor === void ? 0 : +elm.edgecolor;
drawText(x, y, elm.text, color, 255, antialiased, 512, bcolor, 1, 0, 0);
}
else if(shadow)
{
var bcolor = elm.shadowcolor === void ? 0 : +elm.shadowcolor;
drawText(x, y, elm.text, color, 255, antialiased, 255, bcolor, 0, 2, 2);
}
else
{
drawText(x, y, elm.text, color, 255, antialiased); // 文字
}
// Anim_partialImageInfo に情報を追加
addPartialImageInfo(elm);
return 0;
}
function applyColorCorrection(layer, param)
{
// layer に対して色補正を行う
var orgface = layer.face;
var orgholdlpha = layer.holdAlpha;
layer.face = dfAuto;
if(param.grayscale !== void && +param.grayscale) layer.doGrayScale();
layer.adjustGamma(
param.rgamma, param.rfloor, param.rceil,
param.ggamma, param.gfloor, param.gceil,
param.bgamma, param.bfloor, param.bceil);
if(param.mcolor !== void)
{
// 色重ね合わせ
layer.face = dfOpaque;
layer.holdAlpha = true;
layer.colorRect(0, 0, layer.imageWidth, layer.imageHeight, +param.mcolor,
+param.mopacity);
}
if (param.lightcolor !== void) {
// レイヤ合成
var mode = ltAlpha;
if(param.lighttype !== void)
{
var layertypeinfo = imageTagLayerType[param.lighttype];
if(layertypeinfo !== void)
mode = layertypeinfo.type;
}
layer.holdAlpha = true;
layer.fillOperateRect(0,0,layer.imageWidth, layer.imageHeight,
+param.lightcolor,
mode);
}
if (param.shadow !== void) {
// 影つけ
var dx = param.shadowx !== void ? +param.shadowx : 10;
var dy = param.shadowy !== void ? +param.shadowy : 10;
var blur = param.shadowblur !== void ? +param.shadowblur : 3;
var color = param.shadow === true ? 0 : +param.shadow;
var opacity = param.shadowopacity !== void ? +param.shadowopacity : 200;
layer.doDropShadow(dx, dy, blur, color, opacity);
}
layer.face = orgface;
layer.holdAlpha = orgholdlpha;
}
property interrupted
{
// すべてのセグメントに interrupted を設定する
getter() { return Anim_interrupted; }
setter(x)
{
if(Anim_interrupted != x)
{
for(var i = Anim_segments.count -1; i>=0; i--)
{
Anim_segments[i].interrupted = x;
}
Anim_interrupted = x;
}
}
}
function assign(src)
{
// レイヤの情報をコピー
// ただし 位置、透明度、サイズ、レイヤ内画像位置はコピーしない
// (コピーしたい場合は KAGLayer.assignVisibleState を呼ぶこと)
super.assignImages(src);
// アニメーションセルレイヤのコピー
if(src.Anim_cellLayer !== void)
{
if(Anim_cellLayer === void)
Anim_cellLayer = new global.KAGLayer(window, this);
Anim_cellLayer.assignImages(src.Anim_cellLayer);
}
else
{
invalidate Anim_cellLayer if Anim_cellLayer !== void;
Anim_cellLayer = void;
}
// 画像読み込み情報のコピー
if(src.Anim_loadParams !== void)
{
Anim_loadParams = %[];
(Dictionary.assign incontextof Anim_loadParams)(src.Anim_loadParams);
}
else
{
Anim_loadParams = void;
}
// 部分追加読み込みの情報のコピー
if(src.Anim_partialImageInfo !== void)
{
var destinfo;
Anim_partialImageInfo = destinfo = [];
var srcinfo = src.Anim_partialImageInfo;
var count = srcinfo.count;
for(var i = 0; i < count; i++)
{
var info = %[];
(Dictionary.assign incontextof info)(srcinfo[i]);
destinfo.add(info);
}
}
else
{
Anim_partialImageInfo = void;
}
// アニメーションセグメント情報のコピー
// いったん現在のセグメントをクリア
for(var i = Anim_segments.count -1; i>=0; i--)
{
var seg = Anim_segments[i];
invalidate Anim_segments[i] if seg !== void;
}
var srcanimseg = src.Anim_segments; // エイリアス
var src_animseg_count = srcanimseg.count;
var animseg = Anim_segments; // エイリアス
for(var i = src_animseg_count-1; i>=0; i--)
{
var seg = srcanimseg[i];
animseg[i] = void;
if(seg !== void)
{
animseg[i] = new AnimationConductor(this);
animseg[i].number = i;
animseg[i].assign(seg); // アサイン
}
}
animseg.count = src_animseg_count;
// その他
Anim_interrupted = src.Anim_interrupted;
Anim_storageName = src.Anim_storageName;
}
function store()
{
// 情報を辞書配列に記録
var dic = super.store();
// 読み込みパラメータ
if(Anim_loadParams !== void)
{
dic.loadParams = %[];
(Dictionary.assign incontextof dic.loadParams)(Anim_loadParams);
}
else
{
dic.loadParams = void;
}
// 部分追加読み込みの情報
if(Anim_partialImageInfo !== void)
{
var dest;
dic.partialImageInfo = dest = [];
var src = Anim_partialImageInfo;
var count = src.count;
for(var i = 0; i < count; i++)
{
var info = %[];
(Dictionary.assign incontextof info)(src[i]);
dest.add(info);
}
}
else
{
dic.partialImageInfo = void;
}
// アニメーションセグメントの情報を記録
dic.segments = [];
var animseg = Anim_segments; // エイリアス
var animsegcount = animseg.count;
for(var i = 1; i<animsegcount; i++)
{
var seg = animseg[i];
if(seg !== void)
{
if(seg.looping && !seg.stopping && seg.running)
{
// ループ中でかつ停止していなくて停止待ちでもない場合
var dat = %[];
dat.label = seg.startLabel;
dic.segments[i] = dat;
}
}
}
return dic;
}
function restore(dic)
{
// dic から情報を読み出す
loadImages(dic.loadParams);
if(dic.loadParams !== void)
{
// アニメーションセグメントの情報を復元
var dicsegments = dic.segments;
if(dicsegments !== void)
{
var dicsegmentscount = dicsegments.count;
for(var i = 1; i < dicsegmentscount; i++)
{
var seg = dicsegments[i];
if(seg !== void)
loadAnimInfo(i, seg.label, true);
}
}
}
// 部分追加読み込みの情報を復元
if(dic.partialImageInfo !== void)
{
var src = dic.partialImageInfo;
var count = src.count;
for(var i = 0; i < count; i++)
{
var o = src[i];
var tagname = o.tagname;
dm(tagname);
var handler = global.AnimationLayer.Anim_reconstructHandlers[tagname];
dm(handler);
if(handler !== void)
(handler incontextof this)(o);
}
}
else
{
Anim_partialImageInfo = void;
}
super.restore(dic);
}
/*タグハンドラ*/function loadcell(elm)
{
// セルレイヤにセル画像を読み込む
// セルレイヤの確保
if(Anim_cellLayer === void)
Anim_cellLayer = new global.KAGLayer(window, this); // レイヤを作成
// カラーキーの決定
var key;
if(elm.key !== void)
{
// key 指定がある
key = elm.key;
}
else
{
// key 指定がない
key = Anim_loadParams.key; // loadParams の方の key を使う
}
// ストレージ名の決定
var storage;
if(elm.storage !== void)
{
// storage 指定がある
storage = elm.storage;
}
else
{
// storage 指定がない
storage = Storages.chopStorageExt(Anim_loadParams.storage) + "_a";
// loadParams の storage を使う
}
// セルレイヤに画像を読み込む
Anim_cellLayer.loadImages(storage, key);
// セルレイヤに対して色調補正
applyColorCorrection(Anim_cellLayer, Anim_loadParams);
// フリップ
if(Anim_loadParams.flipud !== void && +Anim_loadParams.flipud)
{
// 上下反転
Anim_cellLayer.flipUD();
}
if(Anim_loadParams.fliplr !== void && +Anim_loadParams.fliplr)
{
// 左右反転
Anim_cellLayer.flipLR();
}
return 0;
}
//ryo--
function resetLoop()
{
if(Anim_segments[1]!==void){
if(Anim_segments[1].resetLabel!=""){
// dm("■■キタ━━(゚∀゚)━━!!■■");
Anim_segments[1].timerCallback();
Anim_segments[1].goToLabel(Anim_segments[1].resetLabel);
}
}
}
//--
/*タグハンドラ*/function copy(elm)
{
var lp = Anim_loadParams;
if(lp === void) return -1;
var f;
f = lp.flipud;
var dx = +elm.dx;
var dy = +elm.dy;
var sx = +elm.sx;
var sy = +elm.sy;
var sw = +elm.sw;
var sh = +elm.sh;
var cl = Anim_cellLayer;
if(f !== void && +f)
{
// 上下反転
dy = imageHeight - dy - sh;
sy = cl.imageHeight - sy - sh;
}
f = lp.fliplr;
if(f !== void && +f)
{
// 左右反転
dx = imageWidth - dx - sw;
sx = cl.imageWidth - sx - sw;
}
face = dfAuto;
copyRect(dx, dy, cl, sx, sy, sw, sh);
return 0;
}
/*タグハンドラ*/function s(elm)
{
// 停止
elm.context.running = false;
window.onAnimationStopped(name, elm.context.number);
return -1; // 停止
}
/*タグハンドラ*/function loop(elm)
{
// ループを行うことを宣言する
elm.context.looping = true;
return 0;
}
/*タグハンドラ*/function home(elm)
{
// ホームポジション
return elm.context.stopping?-1:0; // stopping に従って停止
}
/*タグハンドラ*/function clip(elm)
{
// cliprect の変更
setImagePos(-elm.left, -elm.top);
return 0;
}
/*タグハンドラ*/function wait(elm)
{
return elm.time; // 指定時間だけ停止
}
/*タグハンドラ*/function eval(elm)
{
Scripts.eval(elm.exp); // elm.exp を式として実行
return 0;
}
//ryo--
/*タグハンドラ*/function playse(elm)
{
// 効果音の再生
win.se[+elm.buf].play(elm);
return 0;
}
/*タグハンドラ*/function resetpos(elm)
{
elm.context.resetLabel = elm.name;
return 0;
}
//--
}
// pimage, ptext タグのように、栞の読み込み時に再構築
// 可能な情報を復元する際に用いるハンドラ
// (タグ名と、それに対応するハンドラを記述する)
AnimationLayer.Anim_reconstructHandlers =
%[
pimage : AnimationLayer.loadPartialImage,
ptext : AnimationLayer.drawReconstructibleText
];
class ClickGlyphLayer extends AnimationLayer
{
// クリック待ち記号レイヤ
var loadedImage; // 現在読み込まれている画像
var loadedKey; // 現在読み込まれているキー
function ClickGlyphLayer(win, par)
{
// コンストラクタ
super.AnimationLayer(win, par);
hitType = htMask;
hitThreshold = 256; // マウスメッセージは完全に透過
}
function finalize()
{
// finalize()
super.finalize(...);
}
function loadImages(storage, key)
{
// loadImage オーバーライド
if(loadedImage !== storage || loadedKey !== key)
{
super.loadImages(%[storage : storage, key : key]);
loadedImage = storage;
loadedKey = key;
}
}
property visible
{
// visible オーバーライド
getter()
{
return super.visible;
}
setter(x)
{
super.visible = x;
// 非表示の時は動作を停止しているように
if(x)
interrupted = false;
else{
interrupted = true;
}
}
}
}