]> Antirrhinum マニュアル
Antirrhinum マニュアル

目次
§概略
はじめに
成り立ち・位置付け
概要

§ディレクティブ
概要
書式記法
;(コメントアウト)
Rosetta 文
#(ラベル定義)
.if, .elseif, .else, .end ディレクティブ
.while ディレクティブ
.return ディレクティブ
.break ディレクティブ
.continue ディレクティブ
.call ディレクティブ
.jump ディレクティブ
.thread ディレクティブ
.fwait ディレクティブ
.macro, .endm ディレクティブ
.mlet ディレクティブ
.mexpr ディレクティブ

§ユーザーコマンド書式
概要
引数配列タイプコマンド書式
名前付き引数配列タイプコマンド書式
正規表現タイプコマンド書式
メッセージ文書式

§Core コマンド
概要
@wait 文
@wait_for 文
@start_timer 文
@wait_timer 文
@terminate 文
@trace 文
@permit_skip 文
@prohibit_skip 文
@dis_interrupt 文

§書式定義ファイル
概要
<agl_usage_definition> タグ
<script> タグ
<import> タグ
<command> タグ
<message> タグ

§コンパイラツール
コマンドラインツール
AGLCompiler クラス

§AGLCompiler クラス
loadUsageDefFile
loadConfigFile
run
initialize
loadSourceFile
compileSource
saveModuleFile
formatModuleFile
getLastCodeCommand
addCodeCommand
getCompileListener
getConfig
getParserContext
outputError

§AGLCompiler.Listener クラス
概要
initialize
onBeginCompile
onBlankLine
isExtendCommand
beforeAddCommand
onEndCompile

§EntisGLS4 正規表現
概要
文節
文字列
文字
空白
文末
書式の反復
数値ワイルドカード
文節ワイルドカード
閉文字列ワイルドカード
数式ワイルドカード
引数箇所の指定
省略可能箇所の指定
選択可能箇所の指定

§実装
概要
変数スコープ
スレッド毎のインスタンス
セーブ処理
ロード処理
依存処理

§AGLVariablesProcessor
概要
設定ファイル
@init_sflag コマンド
@set_sflag コマンド
@add_sflag コマンド
@add_deed コマンド

§AGLMessageProcessor
概要
設定ファイル
サウンド位置マーカーファイル
メッセージ文
メッセージテキスト書式
@voice コマンド
@voices コマンド
@stopvoice コマンド
@voice_sync コマンド
@msg_window_id コマンド
@showmsg コマンド
@msg_face コマンド
@clr_face コマンド
@pause コマンド
@msg コマンド
@en コマンド
@msg_sync コマンド
@msg_clear コマンド
@enable_skip コマンド
@disable_skip コマンド
@keep_skip コマンド
@scene_skip コマンド
@selector コマンド
@menu コマンド
@endsel コマンド

§AGLSoundProcessor
概要
設定ファイル
@sound_play コマンド
@sound_stop コマンド
@sound_volume コマンド
@sound_wait コマンド
@bgm コマンド
@stopbgm コマンド
@stopse コマンド
@volbgm コマンド
@volse コマンド
@waitse コマンド

§AGLGraphicsProcessor
概要
設定ファイル
レイヤーパス
@screen_init コマンド
@screen_clone コマンド
@screen_delete コマンド
@screen_swap コマンド
@screen_select コマンド
@layer_create コマンド
@layer_image コマンド
@layer_delete コマンド
@layer_exist コマンド
@layer_parameter コマンド
@layer_pre_move コマンド
@layer_add_move コマンド
@layer_start_move コマンド
@layer_wait_move コマンド
@layer_flush_move コマンド
@layer_add_filter コマンド
@layer_clear_filter コマンド
@layer_operate コマンド
@layer_freeze コマンド
@layer_defrost コマンド
@begin_trans コマンド
@begin_trans コマンド
@movie コマンド
@move マクロ
@clear マクロ
@image マクロ
@bg マクロ
@char マクロ
§概略
はじめに
.if isFirstPlay()

ようこそ Antirrhinum スクリプトの世界へ!

${
    resetFirstPlayFlag();
}
.end
 Antirrhinum は EntisGLS4 で提供される疑似言語フレームワークで、ゲーム中のスクリプト記述を容易にカスタマイズして提供することを目的としたインタプリタ言語です。
 コマンドの実装や書式を容易にカスタマイズできるというコンセプトは EntisGLS3 での詞葉言語と同様のものですが、Antirrhinum では付け加え、実装面でのカプセル化が大幅に強化されています。

成り立ち・位置付け
 EntisGLS4 には独自言語として、Sakura2(詞葉言語)仮想マシン、Rosetta スクリプト言語、Antirrhinum の3つが提供されており、それぞれの位置づけが異なります。

 Sakura2(詞葉)は EntisGLS3 で提供されていた独自の言語と仮想マシンのサブセットでしたが、EntisGLS4 では実行のための仮想マシンのみのサブセットが提供されています。
 EntisGLS4 自体は元々詞葉コンパイラの C++ 互換モードでコンパイルできるコードとして記述されています。
(但し、現在は Android での C++ 開発環境が整ってきていることなどから詞葉は使用せず専ら C++ でコンパイルすることしか想定されていませんが、API 群は EntisGLS4 をベース、使用できる文法は C++ 互換モード(凡そ C++98~C++03 相当)を基準としたコードとなっています)

 一方、Rosetta は EntisGLS4 で提供されるスクリプト言語で、ゲーム中のスクリプト言語や、その他テキスト、画像、音声、動画などを簡易に処理することを目的としたインタプリタ言語です。
 また実行時には Sakura2 仮想マシン用のバイナリを出力するコンパイル機能を有しており、Sakura2 の JIT コンパイル機能を利用してネイティブコード化して高速に実行することもできます。
 Antirrhinum コンパイラも Rosetta で記述されています。

 一方で、Antirrhinum は主にゲーム中のスクリプトを記述(高級な処理手順を記述)することを目的としています。
 特にスクリプトとして利用する際に、スクリプト呼び出し側から、スクリプトの途中まで(1フレーム分の処理のみを)実行できる機能を有していることが特徴です(これは Sakura2 仮想マシンにもある機能ですが、Rosetta にはない機能です)。
 EntisGLS4 には Rosetta のインタプリタ、及びコンパイラ機能が提供されるため、Antirrhinum のソースコードは EntisGLS4 上で動的にコンパイルして実行することもできます。

概要
 Antirrhinum コンパイラはプレーンテキストのソースコードをコンパイルし、xml 形式のファイルを出力します。
 コンパイラは Rosetta で記述されており、任意の書式のユーザーコマンドを追加することができます。
 ほとんどの書式は書式定義ファイルをコンパイラに渡すことで任意のコマンドを追加することができます。
 あるいはもっと簡単に、マクロスクリプトでより高級なマクロを定義することができます。ユーザー定義コマンドを追加しないならばマクロは非常に強力です。
 またユーザー定義コマンドでなくても、Antirrhinum スクリプト上から Rosetta スクリプトを実行できるため、Rosetta クラス/関数を供給すれば、ゲーム固有の処理をスクリプト上で容易に記述できます。

 Antirrhinum 仮想マシンでは、実行コマンドとそれの実行プロセッサー(後述 EpicProcessor)は高度にカプセル化されています。
 1つの EpicProcessor は1つのコマンドセットを実装しており、仮想マシンには複数の EpicProcessor を任意に組み合わせて使用できます。
 正しく設計・実装された EpicProcessor は、仮に他の EpicProcessor と依存関係にあっても疎な結合であり、自由な組み合わせで使用することができます。
 GUI の構造が大幅に変更されようとも、あるいは、ノベル・アドベンチャー、RPG、シミュレーション、シューティング、アクション等、ジャンルに依らず、同様の要素は容易に使いまわすことができます。

 本書の後半には標準実装のコマンドを収録していますが、Antirrhinum のコンセプトはユーザー定義コマンドの自由なカスタマイズと、実装のカプセル化ですから、あくまで標準実装コマンドは標準実装コマンドにすぎません。

§ディレクティブ
概要
 Antirrhinum コンパイラは「基本的に」ソースコードを行単位で解釈します。
 行の先頭(空白やタブなどを除いた)に特定の文字 '.'(ピリオド) '$'(ドル) '#'(シャープ) ';'(セミコロン)を見つけると、その行はディレクティブとして解釈されます。


書式記法
 ここでは構文の書式は以下のように表記します。

abc

 装飾されていない(あるいは読みやすさのため太字強調されている)文字や記号はそのまま記述します。


abc

 斜体部分は任意の名前や式を記述します。


abc

abc:
    def

 任意書式 abc の詳細が、行をあけ : 記号以降に定義されています。
 上の例は、任意の def を記述することを意味します。


[ abc ]opt

 [ ]opt で囲まれた部分は省略可能であることを意味します。単に [ abc ] と表記した場合には、角括弧を含めそのままの表記を意味することに注意してください。


{ a | b | c }opt

 { }opt で囲まれた部分は書式が選択的であることを意味します。 | 記号で区切られた範囲が選択可能な一つの書式となります。つまり、上の例は a 又は b 又は c の何れかを記述することを意味します。


;(コメントアウト)
; comment

 コメント行は何も出力されません。

Rosetta 文
$ statement-list
${ statement-list }

statement-list:
    statement ; [ statement-list ]opt

 Rosetta スクリプト文を記述できます。
 ${ } の場合、波括弧の間は複数行に渡って記述することができます。
 Rosetta 文はすべての構文を記述できます。反復文や任意の関数の呼び出しもできますが、長い処理は推奨されません。
(処理中はステートセーブができません。具体的には後述の AGLKernel::Execute 関数から復帰しないためです。)


#(ラベル定義)
# label-name

 ラベル名を定義します。
 ラベルは .call や .jump、.thread 文で処理を開始する行を指定する識別子です。


.if, .elseif, .else, .end ディレクティブ
.if expr
.elseif expr
.else
.end

 .if ディレクティブは expr 条件式が真の時に .if~.else(又は .elseif、.end)までのブロックを実行します。
 条件式の評価が偽の時に .else~.end ブロックが実行されます。


.while ディレクティブ
.while expr
.end

 expr 条件式が真の間 .while~.end ブロックを実行します。


.return ディレクティブ
.return [ if expr ]opt

 .call 呼び出しから復帰、又はスレッドを終了します。
 if で条件式 expr を指定した場合、評価が偽の時には何もしません。


.break ディレクティブ
.break [ if expr ]opt

 .while 反復ブロックから脱出します。
 if で条件式 expr を指定した場合、評価が偽の時には何もしません。


.continue ディレクティブ
.continue [ if expr ]opt

 .while 反復ブロックの先頭に(反復条件判定まで)戻ります。
 if で条件式 expr を指定した場合、評価が偽の時には何もしません。


.call ディレクティブ
.call script#label [ if expr ]opt

script#label:
    { script
    | #label
    | script#label }opt

 サブルーチンを呼び出します。
 if で条件式 expr を指定した場合、評価が偽の時には何もしません。
 script はスクリプトファイル名、label は後述のラベル識別子です。空白文字を含む場合には、'(シングルクォーテーション)、又は "(ダブルクォーテーション)で囲みます。script ファイルの拡張子は省略でき(推奨)、省略した場合には .xmlagl が付加されます。
 ラベル名を省略した場合にはスクリプトファイルの先頭から実行されます。


.jump ディレクティブ
.jump script#label [ if expr ]opt

 処理を移行します。
 if で条件式 expr を指定した場合、評価が偽の時には何もしません。
 script#label 指定は .call ディレクティブと同様です。


.thread ディレクティブ
.thread script#label [ as name ]opt [ if expr ]opt
.thread [ as name ]opt [ if expr ]opt
.end

 サブルーチンをスレッドとして実行します。
 if で条件式 expr を指定した場合、評価が偽の時には何もしません。
 script#label を省略した場合、.thread~.end ブロックをスレッドとして実行します。
 as で name を指定した場合、@terminate 文でスレッドを即時終了させることができます。


.fwait ディレクティブ
.fwait

 実行を1フレーム待機します。


.macro, .endm ディレクティブ
.macro macro-name [: macro-arg-list ]opt
.endm

macro-arg-list:
    macro-arg-definition [, macro-arg-list ]opt

macro-arg-definition:
    { arg-name [= default-value ]opt
    | "arg-name" [= "default-value" ]opt }opt

 .macro ~ .endm ブロックをマクロとして定義します。
 定義したマクロは、ユーザー定義コマンドと同様に、行頭に記述することでマクロを呼び出して展開することができます。
(ユーザー定義コマンドと同名のマクロを定義した場合、マクロ定義が優先されます)
 マクロ引数の定義で、"arg0" のようにダブルクォーテーションで囲むと、その引数は文字列引数として定義され、ダブルクォーテーションで囲んで引数が渡されると、クォーテーション内部の文字列が引数として解釈されます。
 マクロ引数の後ろに = 記号でデフォルト値を定義することができます。
 マクロを展開する際、引数が省略されているとデフォルト値が使用されます。
 マクロ引数は必ず , (コンマ)記号で区切ることに注意してください。

 .macro ~ .endm 間にはマクロの内容を記述します。
 文中にマクロ引数名に一致するトークンが存在すると、マクロとして展開されます。
 マクロ引数をより明示的に記述するには以下のようにします。

%"arg"
"arg" として展開。但しエスケープ文字は修飾されます。
%<arg>
arg として展開。
%(expr)
expr 中のマクロを展開した文字列を数式として評価して展開します。
expr 内に %"arg" や %<arg> を入れ子に記述できますが、%(expr) の多重入れ子は記述できません。

 例えば以下のようなマクロ
.macro マクロ : arg0, arg1, "arg2"="default", arg3=500
@bg black %(arg3/2)
arg0
@bg %"arg2" %(arg3*2)
「%<arg1>」
.endm
を定義し、
マクロ @flash white, きゃぁ
のように記述した場合、
@bg black 250
@flash white
@bg "default" 1000
「きゃぁ」
のように展開されます。
(ユーザー定義コマンド同様、マクロ名はメッセージ文と干渉しないようなマクロ名にすることが必要です)

 マクロ引数に , (コンマ)記号を含めたい場合などには、<> 記号で囲んで記述することができます。
マクロ <@flash white, 200, 3>, ぐはぁぁぁっ!, ev001a, 300
は、
@bg black 150
@flash white, 200, 3
@bg "ev001a" 600
「ぐはぁぁぁっ!」
のように展開されます。

 マクロ文はユーザー定義コマンドと同じように複数のコマンドを1行で記述できる点で似ていますがが、以下のようにユーザー定義マクロでは使用できないディレクティブを含むことができます。
.macro @マクロ : arg0
  .if f.char_mode == 0
    @char %"arg0"
  .else
    @char_d %"arg0"
  .end
.end


.mlet ディレクティブ
.mlet macro-var-name = macro-expr

 マクロ変数を定義します。
 マクロ変数はコンパイル時に評価される変数で、マクロ式中でのみ使用できます。
 マクロ式は、.mlet の右辺、.mexpr ディレクティブ、マクロ展開文中の %() 内でのみ利用できます。

 マクロ変数は、Antirrhinum スクリプトを超えて保持されます(複数のスクリプトを一度にコンパイルする場合に、以前コンパイルした結果が残っています)。


.mexpr ディレクティブ
.mexpr macro-expr

 マクロ式を実行します。
 一度 .mlet ディレクティブで定義しておけば、以下のように代入演算なども .mexpr ディレクティブで実行できます。
.mlet a=0
.mlet b="abc"
.mlet c = new HashMap()
.mexpr ++a
.mexpr b += "def"
.mexpr c[b]=a
.mexpr System.console().printf( "%s\n", b )


§ユーザーコマンド書式
概要
 ディレクティブ以外のコマンドは、任意に追加することができます。
 コマンドの書式には大きく分けて4つのパターンがあり、コマンドごとにそのいずれかを選択して定義することができます。


引数配列タイプコマンド書式
command-name argument-list

argument-list:
    argument [[,]opt argument-list ]opt

argument:
    { parameter
    | "parameter"
    | 'parameter' }opt
例1: @move "target", '1000'
例2: @move target 1000

 初めにコマンド名を記述し、それに続けて引数リストを記述する書式です。
 各引数はクォーテーションで囲むこともでき、また引数同士を ,(コンマ)で区切って記述することもできます。
 引数をクォーテーション記号で囲んだ場合には、文字列は C 言語 \ エスケープシーケンスと同様の処理が施されます。
(但しシングルクォーテーションで囲んだ場合にはダブルクォーテーション、ダブルクォーテーションで囲んだ場合シングルクォーテーションは \ エスケープシーケンス無しでも記述できます)
 クォーテーション記号で囲まない場合、引数は空白(又はタブ)記号で区切られるため、引数に空白を含むことができないことに注意してください。

 引数を省略する場合には、引数を記述せずに(あるいは空白のみで) ,(コンマ)で区切って指定します。
 例1と例2は同じ意味です。
 コマンド名の先頭に @(アットマーク)を付加する必要はありませんが、後述するメッセージコマンドとの干渉を避けたい場合などに、@ や _ などをコマンド名の先頭文字にすることが推奨されます。


名前付き引数配列タイプコマンド書式
command-name named-argument-list

named-argument-list:
    named-argument [[,]opt named-argument-list ]opt

named-argument:
    [ name = ]opt argument

argument:
    { parameter
    | "parameter"
    | 'parameter' }opt
例1: @move id="target" time=1000
例2: @move target time=1000

 初めにコマンド名を記述し、それに続けて名前付き引数リストを記述する書式です。
 この書式の場合、引数を記述する順序は任意となります。
 但し、name を省略することもでき、その場合にはデフォルトの順序で引数を記述することになります。
 また、parameter をクォーテーション記号で囲んだ場合には、文字列は C 言語 \ エスケープシーケンスと同様の処理が施されます。
(但しシングルクォーテーションで囲んだ場合にはダブルクォーテーション、ダブルクォーテーションで囲んだ場合シングルクォーテーションは \ エスケープシーケンス無しでも記述できます)
 parameter をクォーテーション記号で囲まない場合に、空白を含む引数は記述できません。


正規表現タイプコマンド書式
command-name regular-expression

 引数を EntisGLS4 の正規表現形式で指定した書式で記述するタイプです。
(EntisGLS4 の正規表現形式については後述)


メッセージ文書式
regular-expression

 いずれのユーザー定義コマンドにも合致しない場合、これをメッセージ文として EntisGLS4 の正規表現形式で指定した書式で記述するタイプです。
 メッセージ文とは、会話やモノローグなどの文章をゲーム中にメッセージウィンドウなどに出力することを想定したもので、ユーザーコマンドの書式ではない文章をそのまま処理することができる、記述効率と視認性を向上させるための構文です。
 メッセージ文書式は他のユーザー定義コマンドとは異なり、1つしか定義できません。


§Core コマンド
概要
 Core コマンドとは、システムで定義されたユーザー定義コマンドです。


@wait 文
@wait milli-sec

 指定のミリ秒だけ処理を停止します。

※この @wait 文に限らず、すべての待機コマンドは、ユーザーのマウスクリックやスキップモードボタンなどによって、時間が経過しなくても通過する可能性があることに注意してください(標準実装の場合 AGLMessageProcessor クラスによって)。
 ユーザー操作によって待機コマンドが中断されないようにするには、AGLMessageProcessor::GetBehaviorFlags のオーバーライド、@prohibit_skip コマンド、@disable_skip コマンドなどによるスキップ禁止を行ってください。
 AGLMessageProcessor のようにユーザー操作で待機コマンドをスキップさせる作用のある EpicProcessor を使用しない環境下では、待機コマンドが条件以外で通過する心配はありません。


@wait_for 文
@wait_for condition-expr [, timeout-expr ]opt

 condition-expr の評価値が真になるまで停止します。
 timeout-expr を指定した場合、タイムアウト時間(ミリ秒)を指定することもできます。


@start_timer 文
@start_timer

 タイマーをリセットし、この文が実行された時間を 0 とします。


@wait_timer 文
@wait_timer timeout-expr

 @start_timer 実行時点から、timeout-expr で指定された時間(ミリ秒)が経過するまで停止します。
 timeout-expr は一度の待機につき一度だけ評価されます。毎フレーム再評価はされません。但し、再度実行される際には再評価されます。


@terminate 文
@terminate thread-name

 thread-name で指定された名前のスレッドが実行中の場合、即座に終了させます。


@trace 文
@trace trace-string

 デバッグ用のトレース出力へ trace-string 文字列を出力します。
 文字列中に %(expr) 形式の記述がある場合、expr が Rosetta スクリプトの数式として評価され、文字列に置換されて出力されます。


@permit_skip 文
@permit_skip flags

flags
有効にするスキップ機能のフラグの組み合わせ(複数の場合は | 記号で結合)を指定します。
 all : すべてスキップ可能にする
 time : 時間待機をスキップ可能にする
 message : メッセージ待ちをスキップ可能にする
 effect : エフェクト進行時間をスキップ可能にする
 event : イベント同期処理をスキップ可能にする

 このスレッドでの待機命令のスキップを許可します。
※ .thread 文で生成されたスレッドは、デフォルトでは待機命令のスキップは許可されていません。


@prohibit_skip 文
@prohibit_skip flags

 このスレッドでの待機命令のスキップを禁止します。
 flags は @permit_skip と同じです。


@dis_interrupt 文
@dis_interrupt {0|1}opt

 割り込み禁止フラグを設定します。
 通常は禁止フラグは設定されていません(0)。
 割り込み禁止フラグが設定されている(1)と、割り込みの発生が禁止されます。
 キー入力等で割り込みが発生する(特定ラベルへジャンプ/コールする)ような特殊なシステムで、割り込みを発生させたくない区間で禁止フラグを設定します。
 設定された割り込み禁止フラグは、現在のブロック(又は関数)を脱出すると以前の状態に復帰します。
 割り込みを利用する場合でも、このコマンドではなく、割り込みを発生させるシステムで用意されたコマンドで制御すべきです(UI等の連動の為)。


§書式定義ファイル
概要
 書式定義ファイルは、文字通りユーザー定義コマンドの書式を定義したファイルです。
 xml 形式で記述します。

 Antirrhinum コンパイラはソースコードを xml 形式に変換しますが、各コマンドは基本的に1つの xml タグに対応しています。
 書式定義ファイルは、このコマンドごとの対応を記述します。
 また、変則的な処理を行いたい場合には、その処理を Rosetta スクリプトで定義ファイル内に記述することもできます。

 書式定義ファイルを書き換えるだけでスクリプトの書式を容易に定義/変更することができます。


<agl_usage_definition> タグ
 agl_usage_definition タグは書式定義ファイルのルート要素です。


<agl_usage_definition><script> タグ
<script file="rosetta-script-path" [ listener="listener-class" ]opt "/>

 rosetta-script-path に指定された Rosetta スクリプトファイルを読み込みます。
 また、listener-class が指定された場合、インスタンスを作成しコンパイラにリスナを追加します(後述 AGLCompiler.Listener 参照)。


<agl_usage_definition><macro> タグ
<macro file="antirrhinum-macro-path "/>

 antirrhinum-macro-path に指定された Antirrhinum マクロファイルを読み込みます。


<agl_usage_definition><import> タグ
<import file="def-file-path"/>

 def-file-path に指定された書式定義ファイルを追加で読み込みます。
 import タグで読み込まれる書式定義ファイルに import タグがあっても問題ありません。
 また、同じ書式定義ファイルが2回以上 import される場合には、2回目以降は処理はスキップされます。


<agl_usage_definition><command> タグ
<command
    lead="
command-lead-string"
    cmd="
ouput-tag-name"
    arg_type="
{array|named|var_named|usage}opt"
   
[ usage="arg-regular-expression" ]opt >
  <arg_list>
arg-def-list </arg_list>
 
[ <proto_list> prototype-list </proto_list> ]opt
 
[ <proc><![CDATA[
      function( HashMap
params )
          -> AGLCompiler {
rosetta-statement-list } ]]></proc> ]opt
</command>


arg-def-list:
    <arg name="xml-attr-name" [default="default-value"]opt /> [ arg-def-list ]opt

prototype-list:
    <prototype cmd="output-tag-name" [ vararg="1" ]opt >
        proto-arg-list
    </prototype> [ prototype-list ]opt

proto-arg-list:
    <arg name="xml-attr-name"
        [ src="source-param-name" ]opt
        [ value="constant-value" ]opt /> [ proto-arg-list ]opt

 command タグはユーザー定義コマンドの書式と、出力する xml タグの対応を定義します。

 command-lead-string はユーザー定義コマンドのコマンド名に該当します。

 ouput-tag-name と arg-def-list は出力する xml タグのタグ名と、属性名に対応しています。
 arg_type 属性には書式のタイプを指定します。
 array は配列タイプ引数、named は名前付き配列タイプ引数、var_named は名前付き配列タイプ引数ですが、定義された引数以外の名前の記述も可能な書式です。
 arg_type="usage" を指定した場合には arg-regular-expression に書式を EntisGLS4 の正規表現で指定します。

 arg-def-list に指定したパラメータ名(xml-attr-name)をそのまま出力しない場合や、複数の xml タグとして出力する場合には、prototype-list を記述します。
 prototype-list では、一つの prototype タグが、出力する一つの xml タグに対応します。
 vararg="1" を指定したコマンドはプロトタイプに定義されていないパラメータも出力します。

 またより複雑なパラメータへの加工を行いたい場合には、proc タグで処理関数を Rosetta スクリプトで記述できます。
 関数は引数に HashMap を受け取り、これはユーザー定義コマンドをパースした arg-def-list に対応しています。
 スクリプトではパラメータを変更したり、追加することができます。
 また、getParserContext() メソッドで取得できる HashMap オブジェクトに値を保存したり取り出したりして、文脈に依存した処理を行うこともできます。
 処理された HashMap をソースとして prototype-list に基づいた xml タグの出力が行われます。


<agl_usage_definition><message> タグ
<message usage="regular-expression" />
  <arg_list>
arg-def-list </arg_list>
 
[ <parser><![CDATA[
      function( HashMap
params, StringParser parser )
          : boolean -> AGLCompiler {
parser-statement-list } ]]></parser> ]opt
 
[ <proc><![CDATA[
      function( HashMap
params )
          : String -> AGLCompiler {
proc-statement-list } ]]></proc> ]opt
</message>


arg-def-list:
    <arg name="xml-attr-name" /> [ arg-def-list ]opt

 message タグはメッセージ文の書式と、出力する xml タグの対応を定義します。
 通常は regular-expression に EntisGLS4 の正規表現でメッセージ文全体の書式と、出力する xml タグの属性を指定します。
 但し、parser タグにパーサー関数を記述した場合には regular-expression と arg-def-list を指定する必要はありません(無視されます)。

 パーサー関数は1つ目の引数に HashMap を、2つ目の引数にメッセージ文が設定された StringParser を受け取り、関数はメッセージ文を解釈して、HashMap にパラメータを設定し、構文に誤りがなければ true を返却します。
 パーサー関数は単純に1行を処理するだけではなく、getParserContext() メソッドで取得できる HashMap オブジェクトに値を保存したり取り出したりして、文脈に依存した解釈を行うことができます。

 また、ユーザー関数同様に proc タグでは、既に解釈されたパラメータへの加工を行うことができます。
 但しユーザー定義コマンドとは異なり、加工関数は String を返却し、これは出力する xml タグのタグ名となります。
 デフォルトのメッセージ文の出力する xml タグは msg となります。
 単にタグ名を任意に変更したい場合には
<proc><![CDATA[
    function( HashMap params ) : String -> AGLCompiler
    {
        return "msg_tag" ;
    }
]]></proc>
のようにタグ名を返却するだけの関数を記述します。
 null を返却するとそのメッセージ行に対応する xml タグは出力されません。
 複数のタグを出力したい場合や完全にマニュアルで出力したい場合には、加工関数内で addCodeCommand を呼び出し、null を返却します。
(getParserContext() で取得する HashMap に文脈情報を保存しておくことによって、複数行で1つの xml タグを出力することもできます)
§コンパイラツール
コマンドラインツール
antirrhinum[.bat]opt argument-list

argument-list:
    argument [ argument-list ]opt

argument:
    { /def usage-def-file
    | /cfg config-file
    | /dst output-file
    | /dst_dir destination-directory
    | [/src]opt source-file }opt

 コマンドラインツールは、Tools ディレクトリに置かれています。
 コンパイラクラスである AGLCompiler は antirrhinum.rs に記述され、コマンドラインの引数の解釈は antirrhinum_compiler.rs に実装されています。
 antirrhinum.bat は antirrhinum_compiler.rs を呼び出しています。

 デフォルトの書式定義ファイルもこのディレクトリに設置されており、コンパイラは環境変数 ANTIRRHINUM_HOME を参照し、カレントディレクトリにファイルが見つからないとき、%ANTIRRHINUM_HOME%\Tools に相当するディレクトリのファイルを探します。

 usage-def-file には書式定義ファイルを、config-file には設定ファイルを、output-file には出力ファイル名を、destination-directory には出力ディレクトリを、source-file には Antirrhinum スクリプトソースファイルを指定します。
 書式定義ファイルとソースファイルは複数指定することができますが、複数の書式定義ファイルを import する書式ファイルを記述しておけば 1 つにすることができます。
 ソースファイルを複数指定した場合には出力ファイル名は指定できません(同名の .xmlagl ファイルが出力ディレクトリへ出力されます)。

 設定ファイルはコンパイラ(書式定義ファイルから読み込むスクリプトが参照してコンパイルする際)に、設定を反映するためのものです。
 スクリプト毎に自由な設定の書式をとることができますが、基本的に後述の AGLKernel::LoadConfiguration で読み込む設定ファイルと全く同じものを渡してコンパイルできるように設計します。


AGLCompiler クラス
 AGLCompiler を直接使用してコンパイルする場合には以下のような Rosetta スクリプトを記述します。
import "antirrhinum.rs" ;

// AGLCompiler の作成
AGLCompiler compiler = new AGLCompiler() ;

// 設定ファイルの読み込み
compiler.loadConfigFile( "agl_config.xml" ) ;

// ユーザー定義コマンドの書式定義ファイルの読み込み
compiler.loadUsageDefFile( "def_user_cmd1.xml" ) ;
compiler.loadUsageDefFile( "def_user_cmd2.xml" ) ;
...
// マクロスクリプトの読み込み(必要な場合)
compiler.initialize() ;
compiler.loadSourceFile( "macro_script.txt" ) ;

// スクリプトファイルのコンパイル
compiler.run( "source1.txt", "source1.xmlagl" ) ;
compiler.run( "source2.txt", "source2.xmlagl" ) ;
...
 一度 AGLCompiler オブジェクトを作成し、設定ファイル、書式定義ファイルを読み込んでおけば、再度書式定義ファイルを読み込み直さなくても何度でもスクリプトファイルをコンパイルできます。
(ここでは簡略化のためエラー判定を省略しています)

 コンパイル結果をファイルへ書き出さずに直接メモリ上で受け取りたい場合には、run メソッドの代わりに、
compiler.initialize() ;
compiler.loadSourceFile( "source1.txt" ) ;
SmartBufferFile buf = compiler.formatModuleFile() ;
のようなコードで、buf に直接 xml ファイルのバイナリを受け取ることができます。
 この場合でも何度もスクリプトファイルをコンパイルすることができます。
(initialize メソッドでは書式定義やマクロ定義は保持されます)


§AGLCompiler クラス
loadUsageDefFile
public boolean loadUsageDefFile( String strDefFile ) ;

 書式定義ファイルを読み込みます。
 関数が成功すると true が返されます。


loadConfigFile
public boolean loadConfigFile( String strCfgFile ) ;

 設定ファイルを読み込みます。
 関数が成功すると true が返されます。
 読み込んだ XMLDocument は getConfig 関数で取得できます。


run
public int run( String strSrcPath, String strDstPath ) ;

 スクリプトをコンパイルします。
 strSrcPath には Antirrhinum スクリプトファイル名を、strDstPath には出力ファイル名を指定しします。
 関数は発生したエラー数を返します。


initialize
public void initialize( void ) ;

 スクリプトコンパイル用リソースを初期設定します。
 但し、書式定義やリスナの設定などは初期化されません。


loadSourceFile
public int loadSourceFile( String strFilePath, boolean flagNoSuccessReport = false ) ;

 Antirrhinum スクリプトを読み込んでコンパイルします。
 strFilePath にはスクリプトのファイルパスを指定します。
 flagNoSuccessReport に true を指定した場合、エラーが発生しなかった場合には標準出力に結果を出力しません。
 関数は発生したエラー数を返します。

 この関数は run から呼び出されます。


compileSource
public int compileSource( StringParser sparsSrc, String strFilePath, boolean flagNoSuccessReport = false ) ;

 Antirrhinum スクリプトをコンパイルします。
 sparsSrc には Antirrhinum スクリプトを、strFilePath にはスクリプトのファイル名を指定します。
 flagNoSuccessReport に true を指定した場合、エラーが発生しなかった場合には標準出力に結果を出力しません。
 関数は発生したエラー数を返します。

 この関数はファイルを介さずに直接コンパイルすることができます。
 strFilePath は仮のもので構いませんが、AGLCompiler.Listener がファイル名を使って何らかの処理をする場合には、その処理に対して有効な名前にしておく必要があります。
 この関数は loadSourceFile から呼び出されます。


saveModuleFile
public boolean saveModuleFile( String strFilePath ) ;

 コンパイルされた xml をファイルへ出力します。
 strFilePath には出力するファイルパスを指定します。
 関数が成功すると true が返されます。


formatModuleFile
public SmartBufferFile formatModuleFile() ;

 コンパイルされた xml を SmartBufferFile へ出力します。


getLastCodeCommand
public const XMLDocument getLastCodeCommand() ;

 最後に出力された xml タグを取得します。


addCodeCommand
public void addCodeCommand( XMLDocument xmlCmd ) ;

 コマンド用 xml タグを追加します。


getConfig
public const XMLDocument getConfig() ;

 loadConfigFile で読み込んだ XMLDocument を取得します。
 読み込んでいない場合には null が返されます。


getCompileListener
public Listener getCompileListener( Class cls )

 指定されたクラスに適合する Listener を取得します。


getParserContext
public const HashMap getParserContext() ;

 書式処理関数で利用できる HashMap オブジェクトを取得します。
 自由にオブジェクト要素を追加、変更、削除して構いませんが、処理関数同士で副作用がないように注意しなければなりません。


outputError
public void outputError( String sErr ) ;

 エラーを出力します。


§AGLCompiler.Listener クラス
概要
 書式定義ファイルで Rosetta スクリプトを読み込む場合、そのスクリプトで AGLCompiler.Listener 派生クラスを記述し、より複雑なコンパイル処理をカスタマイズすることができます。


initialize
public abstract void initialize( AGLCompiler compiler, XMLDocument xmlTag ) ;

 リスナの初期化処理が必要な場合、ここで行います。
 xmlTag には書式定義ファイルの <script> タグが渡されます。追加的なパラメータをタグの属性に記述しておき、それを使って初期化することができます。


onBeginCompile
public abstract void onBeginCompile( AGLCompiler compiler, String strScriptFile ) ;

 Antirrhinum スクリプトのコンパイルを開始する際に、ファイル毎に呼び出されます。
 strScriptFile には AGLCompiler.compileSource に渡されたファイル名が渡されます。



onBlankLine
public abstract void onBlankLine( AGLCompiler compiler ) ;

 空白行を通過する際に呼び出されます。


isExtendCommand
public abstract boolean isExtendCommand( AGLCompiler compiler, StringParser line ) ;

 ディレクティブやユーザー定義コマンドに合致しない行は、メッセージ文として解釈される前に呼び出されます(空白行は呼び出されません)。
 line にはスクリプト1行が設定されています。
 リスナが何らかの処理を行い、この後コンパイルする必要が無い場合には true を返却します。


beforeAddCommand
public abstract void beforeAddCommand( AGLCompiler compiler, XMLDocument cmd ) ;

 何らかのコマンドがコンパイルされて xml タグが追加される前に呼び出されます。
 cmd 引数には追加される xml タグが渡されます。このタグの中身を変更した場合、その変更は出力に反映されます。
 タグの出力を中止したい場合、
cmd.removeAllContents() ;
のように空の要素に変換すると AGLCompiler はタグを出力しません。
 あるいは setTag 関数で <nop> タグへ置き換えます(<nop> タグは出力されますが、標準実装では何も実行されません)。

 この関数は AGLCompiler.addCodeCommand 関数内から呼び出されるため、この関数内で addCodeCommand 関数を呼び出す場合には無限ループにならないように注意が必要です。


onEndCompile
public abstract void onEndCompile( AGLCompiler compiler ) ;

 Antirrhinum スクリプトをすべて処理し終えた時に呼び出されます(必ず onBeginCompile の呼び出しに対応します)。


§EntisGLS4 正規表現
概要
 EntisLGS4 での正規表現と文字列解釈は SSystem::SUsageMatcher クラスで提供されており、これは EntisGLS3 の正規表現と互換性があります。
 元々この正規表現形式は EntisGLS3 で提供される独自の言語「詞葉」のユーザー定義マクロ構文を記述するためのもので、文字単位より文節単位の処理に適しています。

 1つの文節は、空白記号(タブや改行を含む)か(区切り)記号によって区切られた範囲の文字列です。また当然区切り記号自身も1つの文節となります。
 例えば、
int a=0;
a+=func(b,c);
のようなテキストは、
"int", "a", "=", "0", ";", "a", "+=", "func", "(", "b", ",", "c", ")", ";"
のような文字列配列に分解されます。
 ここで1つ注意すべきことがあります。
 例えば、"+=" はなぜ1つの文節になり、");" は2つの文節に分解されたのでしょうか?
 これに対応する最も原始的な実装は SSystem::SStringParser クラスによって行われ、記号(区切り記号)は、通常の記号(連続した場合1つの文節にする)と、必ず1文字で1つの文節になる特殊区切り記号が定義されていて、この場合、括弧記号はデフォルトで特殊区切り記号として設定されているので分割されます。
 次に疑問に思うのは C 言語などと同等の演算子を記述する場合、>> はどうするのか?ということでしょう。
 このような特殊な文節の判定は、処理したい言語毎に SStringParser から派生したクラスが利用されています。
 しかし正規表現では(直接 SUsageMatcher クラスを利用する場合の除き)SStringParser の実装に暗黙に準じます。
 したがって、文節単位のマッチングでは
>>
> >
は区別できません。>= や <= は注意が必要です。
(厳密には正規表現 >> には > > はマッチングしませんが、正規表現 > > に >> はマッチングします)

 正規表現には文節単位ではない文字や文字列のマッチング書式もあり、組み合わせて記述する必要があります。
 SStringParser では以下の文字が特殊区切り記号として定義されています。
" ' ( ) , ; < > [ ] { }
 記述の通り、特殊区切り記号とは、連続していても1文字1文字が独立した文節として解釈される文字記号です。

 また、記号(区切り記号)として以下の文字が定義されています。
! # $ % & * + - . / : = \ ^ ` | ~
 記号は記号同士が連続している場合、繋がった1つの文節として解釈される文字です。
 @(アットマーク)と _(アンダーバー)は区切り記号として扱われないことに注意してください。


文節
abc
&!abc&

 正規表現は文節単位でマッチングされます。
 &! ~ & で囲まれた文字列は、アルファベットの大文字小文字を区別せずに文節単位でマッチングします。
 & 記号で囲んだ文字列に、&、+、!、\ 記号が含まれる場合、\&、\+、\!、\\ などのように記述する必要があります。

 空白記号(タブや改行含む)は無視されるため、例えば以下のような正規表現
&!This& is a pen .
は、
this  is
a     pen.
にもマッチングします。

文字列
&abc&
&+abc&

 & 記号で囲むことで、文節を考慮しない文字列の一致判定を行うことができます。
 &+ ~ & で囲まれた文字列は、アルファベットの大文字小文字を区別せずに文字列の一致判定を行います。


文字
\single-character
<multi-characters>
<-multi-characters>

 \ 記号に続く1文字は無条件に文節を考慮しない1文字として判定されます。

 < ~ > 括弧で囲むと、その範囲の文字のいずれかの1文字として判定されます。ただし、\、-、<、> 記号は \\、\-、\<、\> のように記述する必要があります。
 また、A-Z のようにハイフンが記述されるとその両隣りの文字の文字コード区間のすべての文字と同等の記述になります。つまり、A-Z は ABCDEFGHIJKLMNOPQRSTUVWXYZ と同等です。また、A-Za-z はすべての半角アルファベットを意味します。

 <- ~ > 括弧で囲むと、その範囲の文字のいずれの文字でもない1文字として判定されます。


空白
 正規表現中のスペースは、0文字以上のスペース記号(タブ、改行コードを含む)にマッチングします。


文末
\

 正規表現末尾の \ 記号は、マッチング対象の文字列の末尾に合致することを指定します。
 正規表現末尾に \ 記号が無い場合には、対象文字列の左側の一致するまでの範囲が対象となります。


書式の反復
abc*

 * 記号直前の書式が1回以上反復することを指定します。
 後述の () や []、{} などの入れ子状になった複数の書式を含んでいても有効です。


数値ワイルドカード
%n

 任意桁の数値(10進数の整数)を指定します。
 {-|[+]} <0-9>* と同じ意味です。([]、{} については後述)

文節ワイルドカード
%t

 任意の文節を指定します。
 記号のみの文節でもマッチングすることに注意してください。


閉文字列ワイルドカード
%cclose-character

 close-character までの文字列を指定します。
 close-character 自身は含まないことに注意してください。
 SStringParser(及び派生クラス)の実装によって終端判定が異なることに注意してください。
 デフォルトの SStringParser 実装では、"(ダブルクォーテーション)と '(シングルクォーテーション)が close-character の場合、C 言語と同様の \ 記号エスケープシーケンスが機能するものとして判定されます。

 例えば以下のような正規表現
"%c""
に対して
"\"hello world\""
をマッチングした場合、%c" にマッチングする箇所は \"hello world\" になります。


文字列ワイルドカード
%s

 任意の文字列を指定します。
 文字列の終端は、%s の直後の書式に合致する最初の位置です。


数式ワイルドカード
%x

 任意の数式を指定します。
 数式の終端は、%x の直後の書式に合致する最初の位置です。
 %s との違いは、"(ダブルクォーテーション)と '(シングルクォーテーション)で囲まれた文字列中、あるいは () 括弧、[] 括弧、{} 括弧で入れ子になった途中で %x の次の書式に合致する箇所があったとしても、それは無視されるという点です。


引数箇所の指定
(abc)

 () 括弧で囲まれた正規表現にマッチングする文字列が引数として抽出され、文字列配列として取得することができます。
 例えば、
if (%x) then (%x) [else (%x)]
のような正規表現([] については後述)に対して、
if a == b then "not else"
のような文字列を処理した場合、
"a == b", "\"not else\"", ""
のような文字列配列を受け取ります。(ここでは便宜上文字列は C 言語 \ エスケープシーケンスを伴って表現しています)



省略可能箇所の指定
[abc]

 [] 括弧で囲まれた正規表現は、省略可能であることを意味します。


選択可能箇所の指定
{a|b|c|...}

 {} 括弧で囲まれ、| 記号で分割される複数の正規表現は、そのいずれかの書式であることを意味します。
 もし複数の正規表現に合致する場合には、一番初めの正規表現が選択されます。
 但し、| で区切られた各正規表現の末尾まで合致しなけば合致したとはみなされません。


§実装
概要
 以下に簡素な Antirrhinum 実装例を示します。
 まず、以下のヘッダファイルをインクルードし、名前空間を以下のように省略するものとします。
#include <sakuraglx/sakuraglx.h>
#include <antirrhinum/antirrhinum.h>
#include <linkgls4.h>

using namespace SSystem ;
using namespace SakuraGL ;
using namespace Rosetta ;
using namespace AntirrhinumGL ;
 初めに、Sakura2 仮想マシンを準備します。
ECSSakura2::EnvironmentVM vmSakura2 ;

vmSakura2.InitializeVM() ;
 Sakura2 仮想マシンは必ずしも必須ではありません。
 また、SGLStdApplication クラスを派生してアプリケーションを記述している場合(推奨)は、GetEnvironmentVM() 関数で初期化済みの ECSSakura2::EnvironmentVM を(StartUpApp、又は Run 関数内で)取得できます。

 次に Rosetta 仮想マシンを準備します。
RSVirtualMachine vmRosetta ;

vmRosetta.Initialize() ;
vmRosetta.AddScriptEnvironmentPath( L"ROSETTA_INCLUDE_PATH" ) ;
vmRosetta.AttachSakura2VM( &vmSakura2 ) ;
 AddScriptEnvironmentPath の呼び出しは必須ではありません。
 ここでは ROSETTA_INCLUDE_PATH 環境変数の値をインクルードパスへ追加しています。
 ゲームのような配布環境では必要なスクリプトファイルはすべて同梱しておきます(通常は書庫ファイル化)。

 必要に応じて Rosetta スクリプトを読み込みます。
SParserErrorLogger perrLog ;
vmRosetta.LoadScript( L"script1.rs", perrLog ) ;
vmRosetta.LoadScript( L"script2.rs", perrLog ) ;
// ...
vmRosetta.CompileToSakura2( true, true, perrLog ) ;
 CompileToSakura2 は読み込んだ Rosetta スクリプトを Sakura2 仮想マシン用の中間コードへコンパイルし、またネイティブコードへコンパイルします。コンパイルは必ずしも必要ではありません(LoadScript のみで実行はできます)。

 いよいよ Antirrhinum の実装に必要なオブジェクトを準備します。
AGLModuleManager aglManager ;
AGLKernel aglKernel ;
AGLEpicCoreProcessor aglCore ;
AGLVariablesProcessor aglVars ;
AGLStdMessageProcessor aglMessage ;
AGLSoundProcessor aglSound ;
AGLGraphicsProcessor aglGraphics ;
 aglVars、aglMessage、aglSound, aglGraphics 等は任意です。
 まず、Antirrhinum 仮想マシン環境を準備します。
aglKernel.AttachRosettaVM( &vmRosetta ) ;
aglVars.AttachRosettaVM( &vmRosetta ) ;
aglKernel.AttachModuleManager( &aglManager ) ;
aglKernel.AttachEpicProcessor( &aglCore ) ;
aglKernel.AttachEpicProcessor( &aglVars ) ;
aglKernel.AttachEpicProcessor( &aglMessage ) ;
aglKernel.AttachEpicProcessor( &aglSound ) ;
aglKernel.AttachEpicProcessor( &aglGraphics ) ;
 AttachEpicProcessor 関数では任意の実装モジュール(EpicProcessor)を追加しています。これによって使用できるコマンドセットを任意にカスタマイズできます。
 AGLEpicCoreProcessor は標準のディレクティブと Core コマンドが実装された EpicProcessor です。
 また、AGLStdMessageProcessor を使用する場合、ここで aglMessage にユーザーインターフェースの設定を行うか、AGLStdMessageProcessor クラス(又は親クラスの AGLMessageProcessor)を派生して実装する必要があります。
 AGLGraphicsProcessor についても表示先の設定を行っておきます。

 次に設定ファイルを読み込みます。
SXMLDocument xmlConfig ;
if ( xmlConfig.LoadDocument( L"agl_config.xml", perrLog ) == errSuccess )
{
    SXMLDocument * pxmlConfig = xmlConfig.GetElementTagAs( L"config" ) ;
    if ( pxmlConfig != nullptr )
    {
        aglKernel.LoadConfiguration( *pxmlConfig ) ;
    }
}
 ルートタグは任意ですが(ここでは <config>)、その要素タグとして各 EpicProcessor 毎の設定を記述し、LoadConfiguration から各 EpicProcessor へ分配され、設定が反映されます。

 ここまでの作業が完了したらコンパイル済みの Antirrhinum スクリプトを実行できます。
aglKernel.InitializeGame() ;

SSmartRef<AGLThread> refThread = aglKernel.BeginThread( L"sample.xmlagl" ) ;
while ( aglKernel.Execute() != AGLThread::statusHalt )
{
    // ...
}

aglKernel.ReleaseGame() ;
 この例では aglKernel.Execute() でループを回していますが、他のループの中で、1フレーム分の処理として aglKernel.Execute() を実行できます。

※実行すべきスレッドが一つもなくなった時に AGLThread::statusHalt を返却しますが、ゲームの作りや Antirrhinum をどこに使うかによって、ゲームを終了する必要があるとは限りません。

※BeginThread の返り値として AGLThread の参照を受け取っていますが、通常アプリケーション側が直接 AGLThread を操作する必要はありません。
 スレッドが終了すれば Execute 内で破棄されます。AGLThread が生存しているかどうかは、aglKernel.IsValidThread を呼び出すことによって確認できます。あるいは単に参照型を nullptr と比較します。

※スクリプトや利用するコマンドによっては aglKernel.Execute() はやや長い時間の処理を行うことがあります(ファイルの読み込みなどを伴うコマンドなど)。コマンドの実装法によってはファイルの読み込み中でも即座に aglKernel.Execute() を復帰するように実装出来ますが、主に会話シーンなどで使うアドベンチャーゲーム用コマンドの標準実装はそうなっていません。
 従ってアドベンチャーゲームや会話シーンなどのスクリプトは通常 UI スレッドではないバックグラウンドスレッドで実行することを想定しています。
 アクションゲームなどの敵のアルゴリズムに Antirrhinum スクリプトを利用する場合にはファイル読み込みなど長い時間のコマンドは用いず、あるいは用いる場合にもコマンド側が非同期処理を行い、コマンドは即時復帰できるように実装する必要があります。
(それ以外の場合には .fwait ディレクティブで aglKernel.Execute() が復帰します)

※会話シーンなどで扱う Antirrhinum スクリプト(バックグラウンドスレッド用)と、敵アルゴリズムなどで扱う Antirrhinum スクリプト(メインループ内用)を併用する場合には、それぞれ別に2つの AGLKernel を作成します(AGLModuleManager や Rosetta 仮想マシンは共通で構いません)。

 尚、終了時には以下のような順序で終了処理を行います。
aglKernel.ReleaseKernel() ;
vmRosetta.Release() ;
 これらの解放関数はデストラクタで自動的に呼び出されるものですが、依存関係があるために明示的に AGLKernel → RSVirtualMachine → ECSSakura2::EnvironmentVM の順に終了処理する必要があります。


変数スコープ
 Antirrhinum では Rosetta スクリプトを実行できますが、単に実行できるだけではなく、フラグも Rosetta を利用します。
 Rosetta スクリプトであらかじめ使用するフラグを作成しておき、Antirrhinum 側で利用することになりますが、グローバルに直接フラグを作成してしまうとゲーム開始時の初期化処理や、セーブ時の処理が複雑になったり、セーブ漏れが生じる原因になります。
 そこで Antirrhinum で利用するフラグのみを格納するクラスを作っておき、Antirrhinum の変数スコープとして設定することで、Antirrhinum 側からの変数の記述をシンプルにし、かつフラグの初期化やセーブ等を簡略化できます。

 典型的には、まず以下のような Rosetta クラスとオブジェクトを定義しておきます。
class AGLVariables
{
    public HashMap f ;
    public HashMap s ;

    public AGLVariables()
    {
        f = {} ;
        s = {} ;
    }
}

AGLVariables g_aglVars = new AGLVariables() ;
 Tools/antirrhinum_vars.rs にもう少し丁寧な AGLVariables 実装がありますので、
import "antirrhinum_vars.rs" ;
AGLVariables g_aglVars = new AGLVariables() ;
としても構いません。
(antirrhinum_vars.rs はゲーム実行時にパスが通る場所に格納(通常は書庫ファイル化するので書庫の中に格納)する必要があります)

 ここで、f は通常のフラグ変数(AGLVariablesProcessor ではゲームフラグと呼び、InitializeGame 関数で初期化されます)、s はゲームを初めからやり直しても初期化されないフラグ変数(同じく共有フラグ)を保存することを想定しています。

 AGLVariables クラスではなく、直接 HashMap を使う場合、
HashMap g_aglVars = { f:{}, s:{} } ;
g_aglVars.freeze() ;
のように freeze することが推奨されます。
(そうでない場合、Antirrhinum 側から Rosetta のグローバル空間へアクセスできなくなります。しかしスクリプト上から Rosetta のグローバル空間にアクセスさせたくない場合や、特定のクラスだけに限定したい場合には、ここにアクセスを許可するクラスを追加し freeze をしないという方法もあります)

 実装側では、上記のような Rosetta スクリプトをロードした後、
RSContext context( &vmRosetta ) ;
RSSmartPtr pVars = vmRosetta.GetMemberAs( context, L"g_aglVars" ) ;
if ( pVars != nullptr )
{
    aglKernel.SetDefaultThisObject( pVars ) ;
}
のように SetDefaultThisObject で変数スコープを設定します。

 こうすると、Antirrhinum 上では、
$f.var1=0;
$f.var2=0;
のように任意の名前の変数を初期化してから
$f.var1++;
.jump #label1 if f.var1>=3
のようにフラグとして利用できます。
(SetDefaultThisObject で g_aglVars を設定しない場合、g_aglVars.f.var1 のような記述が必要になります)

 また、AGLVariables クラスのメソッドをグローバル関数と同じように呼び出すことができますので、antirrhinum_vars.rs を利用した場合、
$clearAllFlags();
$initSFlag( "a", 0 );
のような記述をすることもできます。


スレッド毎のインスタンス
 AGLKernel::BeginThread でスレッドを作成する際、以下のようにスレッド毎に Rosetta インスタンスを作成して設定することができます。
RSSmartPtr pInstance = context.new_Object( L"TypeName" ) ;
aglKernel.BeginThread( L"sample.xmlagl", L"start_label", pInstance ) ;
 スレッドにインスタンスが関連付けられた場合、Antirrhinum スクリプト上からの名前スコープは pInstance になり、AGLKernel::SetDefaultThisObject で設定したものではなくなることに注意してください。
 アクションゲームなどで敵のアルゴリズムを実装する場合などには、このようにスレッド毎にインスタンスを設定します。


セーブ処理
 aglKernel.Execute() 実行中でなければ基本的にいつでもセーブ処理を実行することができます。
(EpicProcessor は Execute 中でなければ基本的にいつでも(AGLKernel 以外の処理の副作用のない範囲で(同期などを行い))セーブできるように実装しなければなりません)

 典型的なセーブ処理は以下のようになります。
SXMLDocument xmlSave ;
xmlSave.SetTag( L"save" ) ;
aglKernel.Serialize( xmlSave ) ;
xmlSave.SaveDocument( L"save.xml" ) ;
 Serialize 関数では、すべてのスレッドの実行状態、及びすべての EpicProcessor がそれぞれ xml の要素タグとして記録されます。


ロード処理
 セーブ処理同様、典型的なロード処理は以下のようになります。
SXMLDocument xmlSave ;
xmlSave.LoadDocument( L"save.xml", perrLog ) ;

SXMLDocument * pxmlSave = xmlSave.GetElementTagAs( L"save" ) ;
if ( pxmlSave != nullptr )
{
    aglKernel.Deserialize( *pxmlSave ) ;
    aglKernel.AfterDeserialize() ;
}
 Deserialize 関数では、すべてのスレッドの実行状態、及びすべての EpicProcessor の状態が、それぞれ対応する xml の要素タグから復元されます。
 ほぼセーブと逆の処理を行うだけですが、復元処理が終わった後に AfterDeserialize 関数を呼び出すことを忘れないでください。

 ロード処理をした後に InitializeGame を呼び出すと初期化処理がされてしまうため、InitializeGame の後にロード処理を行います。


依存処理
 ある EpicProcessor が何かの処理をするとき、別の EpicProcessor の設定等を参照したい場合がまれに生じます。
 例えば、変数の設定や、キャラクターの設定などを参照したい場合、変数の設定なら AGLVariablesProcessor、キャラクターの設定なら AGLMessageProcessor が設定を持っています。
 そういう場合には AGLKernel::GetEpicProcessor 関数を利用します。
AGLMessageProcessor * pMsgProc = GetKernel()->GetEpicProcessor<AGLMessageProcessor>() ;

 また、ある EpicProcessor から何らかの通知などを行いたい場合には、FirstEpicProcessor 関数と NextEpicProcessor 関数を利用することで複数の EpicProcessor を取得できます。
 例えば、AGLMessageProcessor には VoiceListener サブクラスが定義されており、以下のようにボイスの再生に関する通知を行っています。
AGLKernel::EpicProcessorIterator iter = GetKernel()->FirstEpicProcessor() ;
for ( ; ; )
{
    VoiceListener * pListener = GetKernel()->NextEpicProcessor<VoiceListener>( iter ) ;
    if ( pListener == nullptr )
    {
        break ;
    }
    pListener->OnLoadedVoice( voice ) ;
}
 他の EpicProcessor は AGLMessageProcessor::VoiceListener を派生しておくとボイスのロードや再生開始、終了時などに通知を受け取り、例えばキャラクターの表示に連動して音量をパンしたり、口パクをさせたりということが可能です。


§AGLVariablesProcessor
概要
 ゲームで使用するフラグのシリアライズ・デシリアライズを行う標準の EpicProcessor です。
 コマンドセットは書式定義ファイル std_variables_cmd.xml に定義されています。

 AGLVariablesProcessor ではゲームフラグ(ゲーム中でフラグとして使用し、セーブの対象になる HashMap の要素)と、共有フラグ(ゲームを初めからプレイする時にクリアされず保持される HashMap の要素)が管理されています。
 これらフラグの標準的な実装は Tools\antirrhinum_vars.rs に記述されています。

 共有フラグの中には既読(read)フラグ(スクリプト毎にインデックスが振られたメッセージを一度でも読んだことがあるか)や、功績(deed)フラグ(スクリプトラベル通過回数、CG閲覧回数、その他なんらかの実行回数などの記録)が規定の機能として提供されます。
 これらのフラグが、Rosetta スクリプト上のどの変数かは設定ファイルに記述され、設定がない場合、コマンドを実行しても何の作用も発生しません。
 標準的な設定は以下のようになります。
<config>
    <variables
        game_flags="g_aglVars.f"
        shared_flags="g_aglVars.s"
        shared_read=".read"
        shared_deed=".deed"/>
    ...
</config>
 ゲームフラグは標準の初期化・セーブ・ロードフレームワークで処理されますが、共有フラグは AGLKernel 初期設定後(設定ファイル読み込み後)に読み込み、任意タイミング(終了前等)に保存を行う必要があります。

 共有フラグの読み込みは以下のように DeserializeSharedFlags 関数で行うことができます。
SXMLDocument xmlShared ;
xmlShared.LoadDocument( L"shared.xml", perrLog ) ;

SXMLDocument * pxmlShared = xmlShared.GetElementTagAs( L"shared" ) ;
if ( pxmlShared != nullptr )
{
    aglVars.DeserializeSharedFlags( *pxmlShared ) ;
}
 同じく保存処理は以下のように SerializeSharedFlags 関数で行うことができます。
SXMLDocument xmlShared ;
aglVars.SerializeSharedFlags( xmlShared ) ;
xmlShared.SetTag( L"shared" ) ;
xmlShared.SaveDocument( L"shared.xml" ) ;

 ゲームフラグはスクリプト上で初期値を代入すれば初期化できますが、共有フラグは代入してしまうと通常のフラグと変わらずゲームを開始するたびに初期化されてします。
 そこで、フラグ未設定時にのみ値を設定する @init_sflag コマンドや AGLVariables.initSFlag 関数が用意されています。
 通常初回プレイ時に共有フラグは undefined になります。
 以下のようなコードは何度実行しても undefined が出力されます。
@trace "%(s.a)\n"
$s.a++;
 以下のように @init_sflag を初めに実行しておくと実行のたびに値が1増えます。
@init_sflag a 0
@trace "%(s.a)\n"
$s.a++;


設定ファイル
<variables
    game_flags="
game-flags-expr"
    shared_flags="
shared-flags-expr"
    [ shared_read="read-element-name" ]opt
    [ shared_deed="deed-element-name" ]opt />

 ゲームフラグ、共有フラグを設定します。
 read-element-name には既読フラグを格納する要素名を、deed-element-name には功績フラグを格納する要素名を指定します。
 省略した場合にはそれぞれ .read、.deed となります。
 既読フラグや功績フラグを機能させたくない場合には shared_read="" や shared_deed="" のように空文字列を明示する必要があります。

 仮に shared_flags="g_aglVars.s" shared_read=".read" shared_deed=".deed" の時、g_aglVars.s[".read"] に既読フラグ用の HashMap が、g_aglVars.s[".deed"] に功績フラグ用の HashMap が生成されます。


@init_sflag コマンド
@init_sflag var-name  init-expr

var-name
共有フラグ名
init
初期値

 共有フラグが未定義の場合、初期値を設定します。


@set_sflag コマンド
@set_sflag var-name  expr

var-name
共有フラグ名
expr

 共有フラグに値を設定します。
 s["var-name"]=expr と同じ意味です。


@add_sflag コマンド
@add_sflag var-name  expr

var-name
共有フラグ名
expr
加算値

 共有フラグに値を加算します。
 フラグが未定義の場合、初期値として設定します。


@add_deed コマンド
@add_deed var-name

var-name
功績フラグ名

 功績フラグに値を1加算します。
 功績フラグが未定義の場合、初期値として1を設定します。
 このコマンドで加算されたフラグの値は表現可能な整数の最大値を超えることはありません。
 デフォルトでは、スクリプト上のラベルを通過するたびに功績フラグとしてカウントされます(フラグ名は script#label 形式)。
 それ以外で功績フラグを設定したい場合には、スクリプト上で明示的に @add_deed コマンドを記述してください。


§AGLMessageProcessor
概要
 キャラクターのセリフ等を出力する EpicProcessor です。
 ユーザー入力に関係する処理はここに集約されています。
 コマンドセットは書式定義ファイル std_message_cmd.xml(及び std_message_cmd.rs スクリプト)に定義されています。

 AGLMessageProcessor クラスは抽象クラスで、派生クラスで UI やユーザー入力などの実装を行う必要があります。
 UI やユーザー入力を結び付ける標準的な実装の AGLStdMessageProcessor 派生クラスを利用することもできます。

 AGLMessageProcessor では、特に注記のないコマンドでも、文字列(テキストやファイル名等)を受け取るパラメータには、%(~) 形式で、Rosetta 式を含む記述が可能です。


設定ファイル
<message
    [ stop_skip_no_read="{0|1}" ]opt
    [ stop_fast_skip_no_read="{0|1}" ]opt
    [ stop_skip_selector="{0|1}" ]opt
    [ save_in_log="{0|1}" ]opt
    [ nosave_in_skip="{0|1}" ]opt
    [ nosave_in_fast_skip="{0|1}" ]opt
    [ click_cancel_auto="{0|1}" ]opt
    [ click_cancel_skip="{0|1}" ]opt
    [ click_cancel_fast_skip="{0|1}" ]opt
    [ skip_effect_speed="skip-effect-speed" ]opt
    [ msg_window_fade_time="message-window-fade-time" ]opt
    [ msg_log_limit="message-log-limit" ]opt
    [ base_char_vol_line="voice-volume-line-base" ]opt
    [ name_start_chars="name-start-chars" ]opt
    [ name_close_chars="name-close-chars" ]opt
    [ must_name_encloser="must-name-encloser" ]opt
    [ warn_msg_lead_chars="warn-msg-lead-chars" ]opt
</message>
<character_definition [ strict_char_id="{0|1}" ]opt >
    character-definition-list
</character_definition>

character-definition-list:
    <character index="character-index"
       id="
character-id" name="character-name"
        [ name_jp="japanese-char-name" ]opt
        [ name_en="english-char-name" ]opt
        face_file_lead="face-file-lead-name"
        bs_file_lead="bs-file-lead-name"
        volume_line="user-line-index"
        text_color="text-ARGB-hex"
        border_color="border-ARGB-hex"
        shadow_color="shadow-ARGB-hex">
      <bs_file_filter>
          [ file-filter-list ]opt
      </bs_file_filter>
      <voice_file_filter>
          [ file-filter-list ]opt
      </voice_file_filter>
      <voice_file_exception>
          [ file-filter-list ]opt
      </voice_file_exception>
    </character>
    [ character-definition-list ]opt

file-filter-list:
    <filter usage="voice-file-reg-expr"/> [ file-filter-list ]opt

 <message> タグはメッセージの動作設定を保持しています。
 すべての属性は省略可能で、省略時はデフォルトの設定が適用されます。

 stop_skip_no_read は未読メッセージ表示の際にスキップモードを停止、stop_fast_skip_no_read は同じく未読メッセージで高速スキップモードを停止、stop_skip_selector は選択肢でスキップ・高速スキップモードを停止します。
 save_in_log はメッセージログにメッセージ毎のセーブデータを保存、nosave_in_skip は save_in_log=1 の時、スキップモードでのセーブを省略、nosave_in_fast_skip は同じく高速スキップモード時にセーブを省略します。
 click_cancel_auto は画面クリックでオートモード停止、click_cancel_skip は同じくスキップモード停止、click_cancel_fast_skip は同じく高速スキップモード停止です。
 これらの挙動を動的に変化させたい場合には、派生したクラスで GetBehaviorFlags 関数をオーバーライドしてください。

 skip-effect-speed には 0~100 の値で、スキップモード時の画面効果などの進行速度を(時間比を百分率で)指定します。0 は即時、50 は倍速、100 は等速となります。

 message-window-fade-time にはメッセージウィンドウのフェードイン、フェードアウト時間のデフォルト値をミリ秒単位で指定します。

 message-log-limit にはメッセージログの最大保持数を指定します。

 voice-volume-line-base にはキャラクターボイスの音量を個別に設定する場合、そのボリュームラインのベース番号を指定します。
 <character_definition><character > タグの volume_line 属性で指定する値に、この値を加算した番号が、実際の音量ラインとして使用されます。

 name-start-chars、name-close-chars、must-name-encloser はコンパイル時に使用するパラメータで、メッセージ文の名前部分の開始と終了文字を指定できます(後述メッセージ文参照)。

 warn-msg-lead-chars はコンパイル時に、メッセージの先頭の文字に指定文字のいずれかであった場合、エラーを表示するします。例えば "@" を指定すると、コマンドの書き間違えがメッセージ出力となってしまった場合にエラーを出力できます。


 <character_definition> タグは登場人物全般の設定を保持しています。

 character-index は通常 0 から始まる整数で、ゲームのコンフィグ画面などで管理する人物ごとの設定のインデックスと一致させます。
 但し場合によってはマイナスの値を使用することもできます(例えば名前が指定されないメッセージの設定を行いたい場合には -1 を指定します)。

 character-id は登場人物の識別子です。
 メッセージ文でキャラクターを識別するために指定する識別子です(全言語共通)。

 character-name は登場人物の名前です。メッセージウィンドウの名前表示枠に表示する場合などのデフォルトの名前を設定します。この項目は必須ではありません。
 japanese-char-name、english-char-name はそれぞれ多言語対応する場合の、日本語名、英語名を指定します。デフォルトが日本語名の場合には日本語名は不要です(逆にデフォルトが英語名の場合、英語名は不要です)。

 face-file-lead-name はフェイス画像のファイル名の先頭の共通部分です。

 bs-file-lead-name は立ち絵画像のファイル名の先頭部分で人物を判定する場合の共通部分です。

 user-line-index はボイスの音量に適用するボリュームラインのインデックス(0~15 の範囲の整数)です。この数値は <sound><volume_lines><line> の num 属性と共通の値です。
 登場人物ごとに音量設定を持たない場合にはすべての登場人物を 0 にします。

 text-ARGB-hex、border-ARGB-hex、shadow-ARGB-hex は登場人物のセリフを表示する際の文字色、文字縁色、文字影色を ARGB 形式8桁の16進数で指定します。黒は 000000 ではなく、FF000000 であることに注意してください。

 voice-filter-reg-expr には登場人物ごとのファイル名を判別するための EntisGLS4 正規表現を指定します。
 filter タグ要素を複数記述した場合には、それいずれかの条件に合致すれば真になります。

 <bs_file_filter> タグ内には、立ち絵ファイルを判別する条件を記述します。立ち絵ファイルは bs-file-lead-name でも指定できますが両方指定した場合には両方の条件が一致した場合が条件となります。

 <voice_file_filter> タグ内には、ボイスファイルを判別する条件を記述します。いずれかの <filter> タグの条件に一致すれば真となります。
 しかし、<voice_file_exception> タグには除外条件を指定することができ、その要素タグのいずれかに一致する場合には偽となります。


サウンド位置マーカーファイル
<marks>
    marker-list
</marks>

marker-list:
    <mark name="marker-id" pos="position-in-samples" length="length-in-samples"/>
    [ marker-list ]opt

 サウンド位置マーカーファイルは、ボイス等の再生位置とスクリプト処理の同期を取るための情報を格納したファイルです。


メッセージ文
[[name-starter]opt char-id [/name]opt [,face-opt]opt [name-closer]opt]opt [option-parameter-list]opt [{\|}opt]opt text [|voice-file-list]opt

option-parameter-list:
    {+|-|&a|&t=timeout|&f=fadeout}opt [option-parameter-list]opt

:
    space-or-tab-character

voice-file-list:
    voice-file [|voice-file-list]opt

name-starter
名前開始部分を指定する文字です。設定ファイルで定義できます。
char-id
キャラクター識別子。設定ファイル <character_definition><character> タグ id 属性と同じものを指定します。
name
キャラクター表示名。設定ファイルのデフォルトの名前と異なる名前を表示する時に指定します。
%(~) 形式で名前に式を含めることができます。因みに設定ファイルの名前にも %(~) 形式の式を含むことができます。
face-opt
フェイス画像を表示する時、 <character_definition><character> タグ face_file_lead 属性の後置修飾ファイル名を指定します。
(実際のフェイス画像ファイルは face_file_lead と face-opt を結合した名前になります)
省略すると前回と同じフェイスファイルが指定されます。
明示的に空文字列を指定するとフェイスの指定は行われません。
name-closer
名前終了部分を指定する文字です。設定ファイルで定義できます。
option-parameter-list
オプションフラグを記述できます。
+ 記号は以前のメッセージを消去せずに追加表示します。但し直前のメッセージに - 指定されていないと消去されてしまうので追加表示にはなりません。
- 記号はメッセージを進めた時、現在のメッセージを消去しません。
&a はメッセージ表示後にクリックを待たずに次に進みます。
&t=timeout ではタイムアウト時間(ミリ秒)を指定します。タイムアウト時間が指定されるとクリックしなくても時間が経過すると自動的に次に進みます。
&f=fadeout ではフェードアウト時間(ミリ秒)を指定します。フェードアウト時間が指定されると、クリック後のメッセージ消去時にフェードアウト効果を実施します。
text
表示するメッセージ文字列。%(~) 形式でメッセージ中に式を含めることができます。
メッセージ文字列の先頭文字が \ 記号か、スペース、又はタブ記号の場合、その文字は1文字削除されます。
voice-file
再生するボイスファイル名(拡張子は省略可能(.mio))。

 メッセージを出力します。
 メッセージ文は std_message_cmd.rs スクリプトによって文字単位の処理が行われるため、上記書式は文字単位であることに注意してください。

 最も単純な以下のようなメッセージ文
ディレクティブでもユーザー定義コマンドでもない文はメッセージとして出力されます。
は、以下の @msg コマンド(後述)と同等です。
@msg "ディレクティブでもユーザー定義コマンドでもない文はメッセージとして出力されます。"
 キャラクターのセリフとして表示させる場合、キャラクター識別子を指定します。
elena 「今日はいい天気ですね」
 ここで elena は設定ファイルで定義された任意のキャラクター識別子とします。
 キャラクター識別子とセリフは、\ 記号か、スペース、タブ1文字で区切ります。
 キャラクター識別子は日本語でも問題ありませんので、例えば設定ファイルで "エレナ" と定義しておけば
エレナ 「今日はいい天気ですね」
でも問題ありません。但し、名前とセリフの区切り(スペース記号)は必須です。
 より明示的に
エレナ\「今日はいい天気ですね」
と書けます。

 名前の表示を設定ファイルのデフォルトの表示名から変更したい場合には / 記号で区切って指定できます。
エレナ/えれにゃ 「きょうふぁいいてんきでしゅねぇ~」
 フェイス画像を表示するシステムの場合、フェイス画像の差分名を指定できます。
エレナ,n0 「今日はいい天気ですね」
 設定ファイルで face_file_lead="f_elena_" になっている場合、上記で指定されるフェイス画像ファイルは f_elena_n0 となります。
 もちろん表示名を指定した場合にも指定できます。
エレナ/えれにゃ,d1 「きょうふぁいいてんきでしゅねぇ~」

 メッセージの出力にオプション的なパラメータを指定したい場合には、メッセージ本文の前に +, - 記号、又は & 記号でエスケープします。
エレナ-「今日はいい天気ですね~
エレナ+、と思ったら降ってきました」
 オプションパラメータを指定する場合には必ずしもスペースや \ 記号を挿入する必要はありません(挿入しても構いません)。
 しかし必ず必要な場合はあります。
-\ メッセージの先頭に半角スペースを入れたい場合…
+\&、+-&\ などの特定の文字の場合には必要です。
 これらの出力を行うと
 メッセージの先頭に半角スペースを入れたい場合…&、+-&\ などの特定の文字の場合には必要です。
となります。
 また、メッセージ文の先頭がキャラクタ識別子からはじまるモノローグは注意が必要です。
 たまたまキャラクタ識別子の直後に半角スペースがある文があるとキャラクターのセリフとして識別されます。
 モノローグは常にタブで始まるなどの取り決めをしておくと事故を防ぐことができます。

 あるいは、設定ファイルの <message> タグ name_start_chars 属性、及び name_close_chars の属性を設定しておき、スクリプトでは常にその文字で名前を囲んで記述しておけばより確実にコンパイルすることができます。

 例えば設定ファイルに
<message
    name_start_chars="【"
    name_close_chars="】"/>
と記述しておくと、
【エレナ】「今日はいい天気ですね」
のように記述できます。この場合、名前とメッセージ本文間の区切り(\ 記号又はスペース)は省略しても構いません(但しメッセージ本文が半角スペースから始まる場合には余分にスペースを挿入する必要があります)。
 表示名をデフォルトから変更する場合やフェイスを指定する場合も同様に
【エレナ/えれにゃ,d1】「きょうふぁいいてんきでしゅねぇ~」
と記述できます。

 因みに、name_start_chars、name_close_chars を利用して記述する場合、設定ファイルで定義されていないキャラクタのセリフも記述できます。
【モブ】「私は定義されていないキャラです」
 但し、設定ファイルでキャラクタ識別子を空文字列で定義したキャラクタが存在する場合、名前を指定文字で囲まなくても記述することができます。
モブ 「私は character id="" で定義されたキャラです」
 尚、これら定義されていないキャラ、又は "" 識別子のキャラとして処理される場合、常に記述した名前が実行時に表示される名前となります。
 常にスクリプトには常にキャラIDを記述し、もし記述誤りがあった場合にエラーメッセージを出力したい場合には、設定ファイルの <character_definition> タグに strict_char_id="1" 属性を記述してください。
 また、設定ファイルの <message> タグに must_name_encloser="1" を指定すると、名前は常に指定文字で囲む(この例では【~】)ことを意味し、そうでない文はメッセージ本文として解釈されます。

 メッセージ文にボイスファイル指定を記述する場合、文末に | 記号で区切って記述できます。
【エレナ】「今日はいい天気ですね」|v_elena_0001
 複数記述することもできます。
【エレナ】「今日はいい天気ですね」|v_elena_0001|v_elena_0002

 また実装依存ですが、標準の実装の場合、メッセージ本文にはタグで複雑な書式や処理を記述することができます。
 例えば、
【エレナ】<center><font size="200%">「<ruby reading="ヒッサツワザ">必殺技</ruby>!!!」</font></center>
のような記述が可能です。


メッセージテキスト書式
 ここではメッセージ本文に記述できる書式として、EntisGLS4 の SGLSpriteMessage で利用できる書式を説明します。
 書式は xml と同等のタグによって記述できます。
 タグ(及びエスケープ)に使用する半角の < > & 記号自体を記述したい場合には xml 同様にエスケープ表記(&lt; &gt; &amp;)が必要になります。

<font size="font-size" face="font-face" italic="italic" bold="bold" align="horz-align" line_height="line-height" body_argb="text-color" border_argb="border-color" border_width="border-width" border2_argb="border2-color" border2_width="border2-width" shadow_argb="shadow-color"></font>
font-size
フォントサイズ(ピクセル単位)を指定します。
+xxx、-xxx 形式の場合には現在のサイズへの加算、減算、xxx% 形式の場合には現在のサイズへの比率を指定できます。
尚、+xxx、-xxx、xxx% 形式のような現在の値を基準にした形式の場合、行間も自動的に変更されます。
font-face
フォント名を指定します。
italic
true の時斜体、false の時通常
bold
true の時太字、false の時通常
horz-align
left で左寄せ(デフォルト)、right で右寄せ、center で中央寄せ
line-height
行間(ピクセル単位)を指定します。
+xxx、-xxx 形式の場合には現在の行間への加算、減算、xxx% 形式の場合には現在の行間への比率を指定できます。
text-color
文字色を ARGB 形式の16進数で指定します。
border-color
文字縁を ARGB 形式の16進数で指定します。黒は 000000 ではなく FF000000 であることに注意してください。000000 を指定した場合、透明になります。
border-width
文字縁の太さ(ピクセル数)を指定します。
border2-color
文字縁(外側)の色を ARGB 形式の16進数で指定します。
border2-width
文字縁(外側)の太さ(ピクセル数)を指定します。
shadow-color
文字陰の色を ARGB 形式の16進数で指定します。半透明(50%)の黒は 80000000、半透明の白は 80808080 となります。

<style id="style-id"></style>
style-id
定義済みの書式スタイル識別子を指定します。

<center></center>
テキストを中央寄せします。

<right></right>
テキストを右寄せします。

<left></left>
テキストを左寄せします。

<phrase></phrase>
途中でのワードラップを許可しません。
もし途中で行末に到達し改行されてしまう場合には、<phrase> 開始位置で改行します。
※尚、<phrase> を使用しないデフォルトで、アルファベットのみの単語のワードラップ処理は、短い単語は単語の先頭で改行、長い単語はハイフニング(-の挿入)処理が自動的に実施されます。

<br/>
改行します。

<ruby reading="reading"></ruby>
reading
ルビを指定します。

<a href="link-url"></a>
link-url
クリックしたときに実行する URL を指定します。
※デフォルトでは URL はシェルで開かれます。スクリプト自体が遷移するわけではありません。

<xfont id="extend-char-id" pitch="pitch" offset_x="offset-x" offset_y="offset-y" />
extend-char-id
定義済みの外字(画像)識別子を指定します。
pitch
次の文字までの文字間隔(ピクセル単位)を指定します。デフォルトでは画像サイズになります。
offset-x
表示位置の水平調整オフセット(ピクセル単位)を指定します。
offset-y
表示位置の垂直調整オフセット(ピクセル単位)を指定します。

<speed ms_per_char="ms-per-char" fade="fade-time" ></speed>
ms-per-char
メッセージを時間に伴う表示効果を伴って表示する場合、1文字辺りの進行速度(ミリ秒単位の時間)を指定します。
実際の速度は設定によってスケールされます。
設定に関わらず一瞬で表示する場合は 0 です。
fade-time
文字ごとのフェードイン時間(ミリ秒)を指定します。
実際のフェードイン時間は設定によってスケールされます。
ms_per_char=0 が指定された場合、すべての文字が同時にフェードインします。

<wait time="time" />
time
メッセージを時間に伴う表示効果を伴って表示する場合、指定時間(ミリ秒)表示開始を遅延させます。
実際の遅延時間は設定によってスケールされます。


@voice コマンド
@voice voice-file

voice-file
ボイスファイル名(拡張子は省略可能(.mio))

 ボイスを再生します。
 ボイスファイル名と同名で拡張子が .wmk のマーカーファイルが存在する場合、そのファイルも暗黙に読み込まれます。


@voices コマンド
@voices voice1-file [ voice2-file [ voice3-file ... ]opt ]opt

 複数のボイスを同時に再生します。
 ボイスファイル名と同名で拡張子が .wmk のマーカーファイルが存在する場合、そのファイルも暗黙に読み込まれます。


@stopvoice コマンド
@stopvoice fadeout-time

fadeout-time
フェードアウト時間(ミリ秒)

 再生中のボイスを停止します。


@voice_sync コマンド
@voice_sync [ sync-id ]opt

sync-id
再生位置のマーカーID

 再生中のボイスが sync-id 位置を通過するか、sync-id を省略した場合は再生が完了するまで待機します。


@msg_window_id コマンド
@msg_window_id [ message-id ]opt

message-id
出力するメッセージウィンドウのID

 (吹き出しなどで)メッセージウィンドウが複数存在する場合や、複数のタイプのメッセージウィンドウを切り替えて使用する場合、使用するメッセージウィンドウのタイプを指定します。
 message-id を省略、又は "" を指定した時はデフォルトのメッセージウィンドウです。


@showmsg コマンド
@showmsg show  [fade-time]opt

show
0 の時非表示、1 の時表示
fade-time
表示切替の効果時間(ミリ秒)

 メッセージウィンドウを表示・非表示します。


@msg_face コマンド
@msg_face face-file

face-file
フェイス画像ファイル名(拡張子は省略可(但し実装に依存、デフォルトは .eri))

 フェイス画像を表示します。


@clr_face コマンド
@clr_face

 フェイス画像を消去します。


@pause コマンド
@pause timeout=timeout  fadeout=fadeout  keep_msg=keep-message  keep_voice=keep-voice

timeout
タイムアウト時間(ミリ秒)。-1 の時(デフォルト)タイムアウトしない。
fadeout
クリック後、メッセージのフェードアウト時間(ミリ秒)。
keep-message
0 の時クリック後にメッセージを消去(デフォルト)、1 の時メッセージを保持。
keep-voice
0 の時クリック後に再生中のボイスを停止、1 の時はボイスは停止しない。

 メッセージウィンドウのキー入力待ちアイコンを表示し、キー入力を待ちます。
 すべてのパラメータは省略可能です。


@msg コマンド
@msg text=text  name=name  char=char-id  voices=voice-file-list  add_msg=add-message  async=async  timeout=timeout  fadeout=fadeout  keep_msg=keep-message  keep_voice=keep-voice

text
メッセージテキスト。文章中に %(~) 形式で囲んで式を含むことができます。
name
名前表示用テキスト。テキストに %(~) 形式で囲んで式を含むことができます。
char-id で指定されたキャラクターの、設定ファイルで定義されたキャラクター名をそのまま表示する場合には省略できます。
char-id
キャラクター識別子。設定ファイル <character_definition><character > タグ id 属性と同じものを指定します。
name が同じく設定ファイルの登場人物名に一致する場合、あるいはキャラクタを識別しない場合には省略可能です。
voice-file-list
ボイスファイル名を指定します(拡張子は省略可(.mio))。
複数指定する場合には、| 記号で区切って記述します。
add-message
0 の時(デフォルト)直前のメッセージを消去、1 の時、直前のメッセージに追加して出力。
※直前のメッセージで keep_msg=1 を指定しないと、直後のメッセージで add_msg=1 を指定してもすでにメッセージは消去されているので追加はされません。
async
0 の時(デフォルト)メッセージ出力後キー入力を待ちますが、1 の時にはキー入力待ちを行いません。
timeout
タイムアウト時間(ミリ秒)。-1 の時(デフォルト)タイムアウトしない。
fadeout
クリック後、メッセージのフェードアウト時間(ミリ秒)。
keep-message
0 の時クリック後にメッセージを消去(デフォルト)、1 の時メッセージを保持。
keep-voice
0 の時クリック後に再生中のボイスを停止、1 の時はボイスは停止しない。

 メッセージを出力し、キー入力を待ちます。
 text 以外のすべてのパラメータは省略可能です。


@en コマンド
@en text=text  name=name

text
英語用メッセージテキスト。文章中に %(~) 形式で囲んで式を含むことができます。
name
英語用名前表示用テキスト。テキストに %(~) 形式で囲んで式を含むことができます。
設定ファイルで定義された英語名をそのまま表示する場合には省略できます。

 直後の @msg コマンド、又はメッセージ文に英語用のテキストを設定します。


@msg_sync コマンド
@msg_sync [ timeout ]opt

timeout
タイムアウト時間(ミリ秒)。-1 の時(デフォルト)タイムアウトしません。

 メッセージ文字列の表示完了、かつボイスの再生完了まで待機します。


@msg_clear コマンド
@msg_clear

 表示しているメッセージ文字列(発言者名含む)を消去します。


@enable_skip コマンド
@enable_skip sys=sys-skip  click=click-skip  button=button-skip

sys-skip
有効にするスキップ機能のフラグの組み合わせ(複数の場合は | 記号で結合)を指定します。
 all : すべてスキップ可能にする
 time : 時間待機をスキップ可能にする
 message : メッセージ待ちをスキップ可能にする
 effect : エフェクト進行時間をスキップ可能にする
 event : イベント同期処理をスキップ可能にする
 0 : いずれもスキップ可能にしない
click-skip
クリックしたときに有効なスキップ機能のフラグの組み合わせを指定します(sys-skip と同様のフラグ)。
button-skip
有効にするボタンの組み合わせを(複数の場合は | 記号で結合)指定します。
 all : すべてのボタン
 auto : オートモードボタン
 skip : スキップモードボタン
 fast_skip : 高速スキップボタン
 key_skip : スキップ機能に割り当てられたハードウェアキー

 スキップ挙動や、ボタンの有効化を行います。


@disable_skip コマンド
@disable_skip sys=sys-skip  click=click-skip  button=button-skip

sys-skip
無効にするスキップ機能のフラグの組み合わせを指定します。
click-skip
無効にするクリック時のスキップ機能のフラグの組み合わせを指定します。
button-skip
無効にするボタンの組み合わせを指定します。

 スキップ挙動や、ボタンの無効化を行います。
 各パラメータのフラグは @enable_skip と同様です。


@keep_skip コマンド
@keep_skip flags

flags
スキップ機能のフラグの組み合わせを指定します。@enable_skip の click パラメータと同様のフラグです。

 クリック時にスキップ状態を維持するか設定します。
 通常1クリックでは1つの待機状態(画面効果等コマンド)しかスキップしません。
 しかし1クリックで複数のコマンドをスキップしたい場合などで、一連のコマンドの前に @keep_skip all などと記述しておき、スキップを終了したいところで @keep_skip 0 として停止させられます。

@scene_skip コマンド
@scene_skip jump-label

jump-label
シーンスキップでのジャンプ先のラベル名を指定します。
スクリプトファイルを超えてジャンプすることはできません。ラベルの先頭には # をつけずにラベル名を直接指定します。

 シーンジャンプ UI があるシステムで、シーンジャンプボタンを有効化し、ボタンが押されたときに指定のラベルにジャンプするように設定します。
 ジャンプ先ラベルを省略(又は空文字列を指定)すると、シーンジャンプモードは解除され、シーンジャンプボタンは禁止状態(あるいは非表示:挙動は実装依存)になります。
 シーンジャンプが有効な間、@dis_interrupt で割り込みを禁止状態にすると、シーンジャンプボタンを押してもジャンプは発生しません。


@selector コマンド
@selector result  timeout

result
選択結果を受け取る変数を指定します。
timeout
時間制限がある選択肢の場合、制限時間(ミリ秒)を指定します。

 選択肢項目の設定を開始します。
 すべてのパラメータは省略可能です。
 @selector ~ @endsel コマンド間に @menu コマンドで選択し項目を記述します。


@menu コマンド
@menu "text" [ jump jump-label ]opt [ if condition-expr ]opt

text
選択肢と表示する文字列です。%(~) 形式で式を含めることができます。
jump-label
選択肢が選択されたときに、ジャンプ先のラベル名を指定します。
スクリプトファイルを超えてジャンプすることはできません。ラベルの先頭には # をつけずにラベル名を直接指定します。
condition-expr
選択肢を表示する条件式を指定します。

 選択肢として表示する項目を追加します。


@endsel コマンド
@endsel

 選択肢の設定を完了し、実際に画面に表示しユーザーの入力を待ちます。


§AGLSoundProcessor
概要
 サウンド関係を処理する標準の EpicProcessor です。
 コマンドセットは書式定義ファイル std_sound_cmd_ex.xml (基本コマンドのみは std_sound_cmd.xml)に定義されています。

 サウンドインスタンスはチャネル番号毎に生成されます。
 チャネル番号は 0 から始まる整数で、同じ番号にサウンドを読み込むと以前のデータはフェードアウトされ、置き換えられます。
 異なるチャネル番号を指定すると任意数のサウンドを同時に再生できます。

 再生する際にはボリュームラインを指定できます。
 ボリュームラインはいわばサウンドの種類を指定するもので、ゲームの設定によってマスター音量を変更できます。
 既定のボリュームラインは以下のものがあります。
composition (動画等)
system      (システムSE等)
music       (BGM等)
sound       (SE等)
voice       (キャラクターボイス等)
 サウンドファイルには EntisGLS4 標準のフォーマットである mio 形式の他、wav 形式などが利用できます。拡張子に .wpl または .xml を指定した場合プレイリストファイルを再生することができます。


設定ファイル
<sound>
    <volume_lines>
       
line-definition-list
    </volume_lines>
</sound>

line-definition-list:
    <line num="user-line-index" id="user-line-id"/> [ line-definition-list ]opt

 ユーザー定義のボリュームライン名の定義を行うことができます。
 user-line-index には 0~15 の範囲の整数を、user-line-id には定義するボリュームライン名を指定します。
 定義されたボリュームライン名は sound_play コマンドで line に指定できます。


@sound_play コマンド
@sound_play  channel  sound-file  line-id  volume  loop

channel
チャネル番号
sound-file
サウンドファイル名(拡張子は省略可能(.mio))
文字列中に %(~) 形式で Rosetta 式を含むことができます。
line-id
ボリュームライン名
volume
0.0~1.0 の範囲の音量
loop
1 の時強制ループ、0 の時ループ無し

 サウンドファイルを読み込み、再生を開始します。


@sound_stop コマンド
@sound_stop  channel  fadeout

channel
チャネル番号
fadeout
フェードアウト時間(ミリ秒)

 サウンドの再生を停止して破棄します。


@sound_volume コマンド
@sound_volume  channel  volume  fade

channel
チャネル番号
volume
新しい音量 0.0~1.0
fade
フェード時間(ミリ秒)

 サウンドの音量を変更します。


@sound_wait コマンド
@sound_wait  channel

channel
チャネル番号

 サウンドの再生が終了するまで待機します。


@bgm コマンド
@bgm sound-file loop=1 volume=1.0 line=music channel=0

 BGM を再生します。
 @sound_play の BGM 再生用糖衣構文です。
※書式中パラメータの = は省略時のデフォルト値


@se コマンド
@se sound-file loop=0 volume=1.0 line=sound channel=1

 SE を再生します。
 @sound_play の SE 再生用糖衣構文です。
※書式中パラメータの = は省略時のデフォルト値


@stopbgm コマンド
@stopbgm fadeout=1000 channel=0

 BGM を停止します。
 @sound_stop の BGM 停止用糖衣構文です。
※書式中パラメータの = は省略時のデフォルト値


@stopse コマンド
@stopse fadeout=0 channel=1

 SE を停止します。
 @sound_stop の SE 停止用糖衣構文です。
※書式中パラメータの = は省略時のデフォルト値


@volbgm コマンド
@volbgm volume fade=500 channel=0

 BGM の音量を変更します。
 @sound_volume の BGM 音量変更用糖衣構文です。
※書式中パラメータの = は省略時のデフォルト値


@volse コマンド
@volse volume fade=500 channel=1

 SE の音量を変更します。
 @sound_volume の SE 音量変更用糖衣構文です。
※書式中パラメータの = は省略時のデフォルト値


@waitse コマンド
@waitse channel=1

 SE の再生が終了するまで待機します。
 @sound_wait の SE 再生完了待機用糖衣構文です。
※書式中パラメータの = は省略時のデフォルト値


§AGLGraphicsProcessor
概要
 2Dグラフィック関係の処理を行う標準の EpicProcessor です。
 コマンドセットは srd_graphics_cmd_ex.xml(基本コマンドのみは std_graphics_cmd.xml)に定義されています。
(srd_graphics_cmd_ex.xml は、std_graphics_cmd.xml 定義ファイルと std_graphics_cmd_ex.txt マクロファイルを読み込みます)

 実装のベースは EntisGLS4 の Sprite です。
 AGLGraphicsProcessor では階層化された複数のレイヤーと、レイヤーのルートである複数のスクリーンを扱うことができます。

 画像はレイヤーに読み込んで表示することができますが、キャラクターの立ち絵など、レイヤーにはスタイルを指定することができ、座標指定をわかりやすく記述することができます。

 また、AGLGraphicsProcessor では、コマンドのほとんどの引数に、数値の場合には Rosetta での数式、また文字列引数には %(~) 形式で文字列中に数式の評価値を含むことができます。
 座標などの定数を Rosetta で定義しておくと AGLGraphicsProcessor コマンドでも使用できます。


設定ファイル
<graphics>
    <styles style-parameters >
        style-definition-list
    </styles>
    [ <init_screen screen="screen-index" style="style-id" /> ]opt
</graphics>

style-definition-list:
    <style id="style-id" ref="ref-sryle-id" style-parameters /> [ style-definition-list ]opt

style-definition-list:
    layer_type="layer-type"
    priority="priority"
    layer_width="layer-width"
    layer_height="layer-height"
    offset_x="offset-x"
    offset_y="offset-y"
    pivot_x="pivot-x"
    pivot_y="pivot-y"

layer-type:
    { layer
    | buf_layer
    | layer_set
    | fb_vram
    | fb_ram
    | fb_cpu }opt

 設定ファイルにはレイヤースタイルの定義と、InitializeGame 時に自動的に初期スクリーンを作成する場合には <init_screen> タグにスタイルを指定します。

 <styles> タグに直接記述したレイヤースタイルは、デフォルトのレイヤースタイルです。空文字列のスタイルIDとして参照できます。
 追加的なスタイルは <style> タグで行えますが、ref-style-id に参照スタイルIDを指定でき、その場合、先に定義したスタイルをベースに変更したいパラメータだけを記述できます。

 layer-type にはレイヤーのバッファの処理方式を指定します。
 単に画像を表示したいだけのレイヤーは layer を指定します。
 スクリーンのスタイルには通常は fb_ram を指定します。
 buf_layer, fb_vram, fb_ram, fb_cpu はフレームバッファを作成します。フレームバッファサイズは layer-width, layer-height になります。
 buf_layer は画像を表示するためのレイヤーですが、新しい画像をそのレイヤーに読み込む場合、古い画像を自動的にクロスフェードして表示する出来る機能を持ったレイヤーです。
 layer_set はフレームバッファを作成せずにサブレイヤーを作成できるレイヤーです。
 サブレイヤーの表示位置(拡大・回転・透明度等含む)はその親レイヤーの影響を受けます。
 fb_vram は VRAM 上にフレームバッファを作成します。
 fb_ram は RAM と VRAM 上にフレームバッファを作成します。GPU での描画の後のフィルター処理を CPU でも行うことができます。fb_vram では一部のフィルターが動作しない可能性がありますが、fb_ram より高速です。
 fb_cpu は RAM 上にフレームバッファを作成し、描画も CPU で行います。

 priority にはデフォルトの表示優先度(整数)を指定します。
 優先度は 0 が基準優先度で、大きな数のほうが奥に表示されます。
 実装上の実際の Sprite の優先度は、AGLGraphicsProcessor に設定された基準優先度に加算されます。
 スクリーンの優先度は、他の画面表示アイテムと干渉しない為に -100~+100 の範囲で使用すべきです。
 レイヤーの優先度は自由な範囲で利用できます(しかし内部の優先度加算処理の結果を安全な範囲に保つため、30ビットで表現可能な程度の数値にすべきです)。

 pivot-x, pivot-y にはソース画像(フレームバッファ)の中心座標を指定します。
 この座標は拡大縮小や回転の中心座標になるほか、表示座標の位置を示すものにもなります。つまり、pivot 座標と同じ表示座標にレイヤーを表示したとき、画像の左上が 0, 0 になります。
 但し、画像ファイルにはオフセット座標が格納されており(eri 形式の場合)、例えばキャンバスサイズが画面サイズに一致する PSD ファイルから透明でない部分のみを書き出した場合、ファイルの画像サイズは PSD のキャンバスサイズとは必ずしも一致しませんが、読み込んで 0,0 に表示した場合(pivot も 0,0 の場合)、PSD で表示した時と同じ位置に表示されます。
 従って、pivot は画像ファイル上のローカル座標ではなく、PSD で表示したときに中心にしたい座標を設定することになります。

 offset-x, offset-y には、実際に表示する座標をコマンド引数で指定した座標に加算する値を指定します。
 pivot を設定した場合、offset を同じ座標にすることによって、スクリプトで指定する 0,0 が pivot の位置になります。


レイヤーパス
[ parent-layer-path . ] layer-id

 @layer_~ 系コマンドには、layer パラメータにレイヤーパスを指定します。
 レイヤーには個別に任意の ID を設定することができますが、これは大域的な ID ではなく、そのレイヤーセット内の局所的な ID です。
 レイヤーパスは親レイヤーと子レイヤーを . (コンマ)記号で結合して記述します。
 空文字列、又は . だけのレイヤーパスはルートレイヤー(スクリーン自体)を指定します。


@screen_init コマンド
@screen_init  screen=screen  priority=priority  visible=visible  style=style  layer_type=layer-type

screen
スクリーン番号
priority
表示優先度
visible
true で表示状態、false で非表示状態
style
レイヤースタイルID
layer-type
レイヤータイプ(設定ファイル参照)
省略時はレイヤースタイルでの定義が使用されます。

 指定のスクリーン番号に新規スクリーンを作成します。
 既にスクリーン作成済みの場合には何もしません。


@screen_clone コマンド
@screen_clone  screen  src-screen  priority

screen
新規スクリーン番号
src-screen
複製元スクリーン番号
priority
表示優先度

 指定のスクリーン番号に複製元スクリーンの複製を作成します。


@screen_delete コマンド
@screen_delete  screen

screen
削除スクリーン番号

 指定のスクリーン番号のスクリーンを削除します。


@screen_swap コマンド
@screen_swap  screen  src-screen

screen
スクリーン番号1
src-screen
スクリーン番号2

 二つの指定のスクリーンの番号を入れ替えます。
 片方のスクリーン番号が削除(あるいは未作成)の番号でも有効です。


@screen_select コマンド
@screen_select  screen

screen
選択スクリーン番号

 指定のスクリーン番号を選択します。
 現在選択されているスクリーンは @layer~ 系コマンドの対象スクリーンとなります。


@layer_create コマンド
@layer_create  layer=layer  id=id  class=class  style=style  layer_type=layer-type [ layer-parameters ]opt

layer
親レイヤーパス
現在のスクリーン直下に作成する場合には "" か . を指定します。
id
作成レイヤーID
class
作成レイヤークラス
layer, image, movie 等
style
レイヤースタイルID
省略した場合はデフォルトスタイルが適用されます。
layer-type
レイヤータイプ(設定ファイル参照)
省略時はレイヤースタイルでの定義が使用されます。
layer-parameters
レイヤーパラメータ(@layer_parameter 参照)

 レイヤーを作成します。
 class 指定によってさまざまな種類のレイヤーを作成することができます。
 追加の固有レイヤーを実装したい場合には、派生クラスで NewLayerItem 関数と OnInitLayerItem 関数をオーバーライドします。


@layer_create  class=image  file=image-file  [ layer-create-parameters ]opt

image-file
画像ファイル名
拡張子を省略すると .eri が適用されます。
layer-create-parameters
@layer_create のパラメータ

 レイヤーを作成し、画像を読み込みます。

@layer_create  class=movie  file=movie-file  [ layer-create-parameters ]opt

movie-file
動画ファイル名
拡張子を省略すると .mei が適用されます。
layer-create-parameters
@layer_create のパラメータ

 動画再生用レイヤーを作成し、動画ファイルを読み込みます。


@layer_image コマンド
@layer_image  layer  image-file  fade-time

layer
対象レイヤーパス
image-file
画像ファイル名
拡張子を省略すると .eri が適用されます。
fade-time
切り替えフェード時間 [ms](デフォルトは 0)

 指定レイヤーに画像を読み込みます。
 layer_style=buf_layer で作成されたレイヤーの場合、画像の切り替えをフェード表示させることができます。


@layer_delete コマンド
@layer_delete  layer

layer
対象レイヤーパス

 指定レイヤーを削除します。


@layer_exist コマンド
@layer_exist  layer  result-expr

layer
対象レイヤーパス
result-expr
結果を受け取る変数

 レイヤーが存在しているか調べ、result-expr に結果を設定します。
 レイヤーが存在しているときには -1 が、存在しない場合には 0 が設定されます。


@layer_parameter コマンド
@layer_parameter  layer=layer  layer-parameters

layer-parameters:
    x=coord-x
    y=coord-y
    dx=delta-x
    dy=delta-y
    sx=scale-x
    sy=scale-y
    rz=rotate-z
    tr=transparency
    fp=filter-param
    fp2=filter-param2
    priority=priority
    visible=visible

layer
対象レイヤーパス
coord-x
x座標(デフォルトは 0)
coord-y
y座標(デフォルトは 0)
delta-x
x座標加算値(デフォルトは 0)
delta-y
y座標加算値(デフォルトは 0)
scale-x
x拡大率(デフォルトは 1.0)
scale-y
y拡大率(デフォルトは 1.0)
rotate-z
回転角度 [deg](デフォルトは 0)
transparency
透明度(デフォルトは 0)
0~256 の整数で、0 の時不透明、256 の時完全に透明になります。
filter-param
フィルタパラメータ(デフォルトは 0)
ほとんどのフィルタで、0 の時無効果、256 の時 100% 効果状態です。
filter-param2
フィルタ第二パラメータ(デフォルトは 0)
トランジッションフィルタなどで、トランジッションの進行度を 0~256 の範囲で指定します。
priority
レイヤー表示優先度
visible
true で表示状態、false で非表示状態

 指定レイヤーのパラメータを変更します。


@layer_pre_move コマンド
@layer_pre_move  layer  offset-mode

layer
対象レイヤーパス
offset-mode
true の時オフセットアニメーション、false の時絶対座標(ローカル座標)アニメーションとなります(デフォルトは false)

 パラメータアニメーションの準備を行います。
 パラメータアニメーションは通常のレイヤー(class=layer や class=image)のみが対応した機能で、動画レイヤー等の特殊レイヤーは対応していません。
 従って、特殊レイヤーでパラメータアニメーションを行いたい場合には、layer_set レイヤーを作成し、その子レイヤーとして動画などの特殊レイヤーを作成し、パラメータアニメーションは layer_set レイヤーに対して行う必要があります。


@layer_add_move コマンド
@layer_add_move  layer=layer  time=move-time  v0=start-point-velocity   v1=end-point-velocity  layer-parameters

layer
対象レイヤーパス
time
追加する区間に要する時間 [ms]
start-point-velocity
追加した区間の開始地点の速度比(デフォルトは 1.0)
end-end-velocity
追加した区間の終了地点の速度比(デフォルトは 1.0)
layer-parameters
レイヤーパラメータ(@layer_parameter 参照)
但し、visible, priority はアニメーション対象外です。

 アニメーションのパラメータを追加します。
 start-point-velocity, end-end-velocity には 0.0, 0.0 の組み合わせなら静止→加速→減速→静止移動に、1.0, 1.0 なら等速運動、0.0, 2.0 なら静止→加速の等加速度運動、2.0, 0.0 なら減速→静止の等加速度運動となります。


@layer_start_move コマンド
@layer_start_move  layer  loop-type  offset-mode

layer
対象レイヤーパス
loop-type
ループタイプ(デフォルトは once)
ループしない場合は once、ループする場合は loop、反転ループする場合は turn を指定します。
offset-mode
true の時オフセットアニメーション、false の時絶対座標(ローカル座標)アニメーションとなります(デフォルトは false)

 パラメータアニメーションを開始します。


@layer_wait_move コマンド
@layer_wait_move  layer  all-layers

layer
対象レイヤーパス
all-layers
true の時対象レイヤーの子レイヤーすべて、false の時対象レイヤーのみ

 レイヤーのパラメータアニメーションが完了するのを待機します。


@layer_flush_move コマンド
@layer_flush_move  layer  all-layers  all-moving

layer
対象レイヤーパス
all-layers
true の時対象レイヤーの子レイヤーすべて、false の時対象レイヤーのみ
all-moving
true の時ループを含む全アニメーション、false の非ループアニメーションのみ

 レイヤーのパラメータアニメーションを強制的に即時終了させます。
 パラメータはアニメーション完了時の値になります。


@layer_add_filter コマンド
@layer_add_filter  layer=layer  filter=filter-class  [ filter-parameters ]opt

layer
対象レイヤーパス
filter-class
フィルタークラス
filter-parameters
フィルター固有パラメーター

 レイヤーにフィルターを設定します。
 フィルターは複数設定することができますが、フレームバッファを所有するレイヤーでなければなりません。
 固有のフィルターを追加実装したい場合には派生クラスで CreateSpriteFilter 関数をオーバーライドします。


@layer_add_filter  layer=layer  filter=transparency

 透明度フィルターを設定します。
 フィルタパラメータが透明度として扱われます。


@layer_add_filter  layer=layer  filter=alpha_mask  alpha_file=alpha-file  alpha_coef=alpha-coef

alpha-file
α画像ファイル
拡張子を省略すると .eri が適用されます。
alpha-coef
α係数(デフォルトは 256)

 α画像マスクフィルターを設定します。
 alpha_coef=256 の時にフィルタパラメータに 128 を設定する(@layer_parameter fp=128)と、丁度α画像でマスクした表示状態になります。
 このフィルタは、現在のバージョンでは CPU のみで動作します。


@layer_add_filter  layer=layer  filter=tone_curve  tone_file=tone-curve-file

tone-curve-file
トーンカーブファイル
拡張子を省略すると .tcf が適用されます。

 トーンカーブフィルタを設定します。
 フィルタパラメータに 256 を設定した時(@layer_parameter fp=256)、トーンカーブ適用度が 100% になります。
 このフィルタは、現在のバージョンでは CPU のみで動作します。


@layer_add_filter  layer=layer  filter=shading_off  transition=transition  over_color=hex-over-color

transition
true の時トランジッション動作、false の時フィルタのみの動作になります。
トランジッション動作時にはフィルタ第二パラメータが透明度になります。
hex-over-color
フィルタ処理の後に描画する色を ARGB 形式の16進数で指定します。
00000000 の時には色効果はありません(デフォルト)。
00FFFFFF の時にはフィルタパラメータに連動して徐々に白色発光(加算)するような効果が得られます。

 ぼかしフィルタを設定します。
 CPU/GPU どちらでも動作しますが、CPU の場合重いので GPU での動作が推奨されます。


@layer_clear_filter コマンド
@layer_clear_filter  layer

layer
対象レイヤーパス

 レイヤーのフィルターをすべて解除します。


@layer_operate コマンド
@layer_operate  layer=layer  operate=operate  [ operate-parameters ]opt

layer
対象レイヤーパス
operate
レイヤー操作コマンド
operate-parameters
操作パラメーター

 レイヤー固有の操作を行います。
 追加の固有操作を追加したい場合には派生クラスで OperateLayer 関数をオーバーライドします。


@layer_operate  layer=layer  operate=movie_play  loop=loop-flag

loop-flag
true の時ループ再生します。

 動画の再生を開始します。


@layer_operate  layer=layer  operate=movie_stop

 動画の再生を停止します。


@layer_operate  layer=layer  operate=movie_wait

 動画の再生が完了するまで待機します。


@layer_freeze コマンド
@layer_freeze  layer

layer
対象レイヤーパス

 フレームバッファを所有するレイヤーの表示更新を停止します。
 @layer_freeze を実行したのと同じ回数だけ @layer_defrost を実行すると表示の更新が再開されます。


@layer_defrost コマンド
@layer_defrost  layer

layer
対象レイヤーパス

 一時停止されたレイヤーの表示更新を再開します。


@begin_trans コマンド
@begin_trans  time=time  filter=filter-class  [ filter-parameters ]opt

time
トランジッション時間 [ms]
filter-class
フィルタークラス(デフォルトは transparency)
filter-parameters
フィルター固有パラメーター

 トランジッションの準備をします。
 このコマンドではスクリーン 0 をスクリーン 1 に複製し、フィルタを設定します。
 @begin_trans ~ @end_trans 間に新しい画面への変更処理を記述することによって簡易に画面切り替えを行います。

@end_trans コマンド
@end_trans

 画面を切り替えます。
 スクリーン 1 は削除されます。


@movie コマンド
@movie  file=movie-file  x=coord-x  y=coord-y  sx=scale-x  sy=scale-y

movie-file
動画ファイル名

 スクリーン 2 を表示優先度 99 で作成し、レイヤー ID = movie の動画レイヤーを作成して再生、終了するまで待機し、終了するとスクリーン 2 を削除します。
 座標等のパラメータは省略可能です(@layer_parameter に指定できるパラメータは一通り指定可能です)。
 スクリーン 2 を作成するスタイルとして movie_screen、movie レイヤーを作成するスタイルとして movie_layer が暗黙に指定されますので、設定ファイルで定義しておけば位置などの設定を行うことができます。


@move マクロ
@move  layer , time , coord-x , coord-y , transparency , rotate-z

 layer に指定したレイヤーを、移動(coord-x, coord-y)、回転(rotate-z [deg])、透明度(transparency)に指定時間(time [ms])だけかけて変化させます。


@clear マクロ
@clear  layer , time , delta-x , delta-y

 layer に指定したレイヤーフェードアウトさせてから削除します。
 delta-x, delta-y を指定すると座標を移動させながらフェードアウトします。


@image マクロ
@image  layer , image-file , time , priority , coord-x , coord-y , transparency , rotate-z , layer-style

 layer に指定したレイヤーに画像を読み込みます。
 またレイヤーが既に存在する場合、指定座標(coord-x, coord-y)、透明度(transparency)、回転角(rotate-z)に移動アニメーションします。
 またレイヤータイプが buf_layer の場合、画像はクロスフェードしながら切り替わります。

 レイヤーが存在しない場合、新規にレイヤーを作成して画像を読み込み、フェードインします。
 レイヤー作成時の layer-style は、省略すると image が参照されます。

 このマクロはレイヤーが存在するかをテストするために f.@layer_exist フラグに @layer_exist コマンドの結果を受け取ります。


@bg マクロ
@bg  image-file , time

 レイヤー ID = bg、表示優先度 100、座標 (0,0)、デフォルトのレイヤースタイル bg でレイヤーに画像を読み込みます。
 このマクロは @image マクロを呼び出します。


@char マクロ
@char  layer , image-file , time , coord-x

 レイヤー ID = layer、表示優先度 50、座標 (coord-x,0)、デフォルトのレイヤースタイル char でレイヤーに画像を読み込みます。
 このマクロは @image マクロを呼び出します。

 y 座標は暗黙に 0 ですので、画像データの作成時、あるいはレイヤースタイルで y 座標が 0 で問題ないように設定します。