LScript 2.0 マニュアル

LScript Ver. 2.0
日本語マニュアル
ファイルオブジェクト
LScriptの概要 - - - - - - - - - - - - - - - - - - - - - -1
ファイルの名称 - - - - - - - - - - - - - - - - - - -13
LScriptの実行 - - - - - - - - - - - - - - - - - - - - - -1
ユーザー作成のオブジェクトエージェント 15
本章で使用する書式 - - - - - - - - - - - - - - - - -2
本書で使用する書体 - - - - - - - - - - - - - - - - -2
- - - - - - - - - - - - - -12
ビルトイン関数 - - - - - - - - - - - - - - - - - - - -15
事前定義値
LScriptの内部 - - - - - - - - - - - - - - - - - - - - - -3
- - - - - - - - - - - - - - - - - - - - - -15
イメージフィルター - - - - - - - - - - - - - - - - - -16
mainプロシージャ - - - - - - - - - - - - - - - - - -3
プロシージャルテクスチャ - - - - - - - - - - - - -16
ユーザー定義プロシージャ - - - - - - - - - - - -3
変位マップ - - - - - - - - - - - - - - - - - - - - - - - -16
ライブラリ
オブジェクト置換 - - - - - - - - - - - - - - - - - - -16
- - - - - - - - - - - - - - - - - - - - - - -4
LScript言語の構造 - - - - - - - - - - - - - - - - - - -5
内部コマンド - - - - - - - - - - - - - - - - - - - - -16
言語で使うキーワード - - - - - - - - - - - - - - -5
LightWave Modelerコマンドおよび関数 - -25
LScript内のコメント
- - - - - - - - - - - - - - - -5
LightWave Layoutコマンドおよび関数 - - -48
LScriptの制御構造 - - - - - - - - - - - - - - - - - - -6
レイアウトのLScript - - - - - - - - - - - - - - - -48
LScriptのデータ型 - - - - - - - - - - - - - - - - - - -9
レイアウトのスクリプト構造
数値
- - - - - - - - -48
共有関数 - - - - - - - - - - - - - - - - - - - - - - - -49
- - - - - - - - - - - - - - - - - - - - - - - - - - - -9
文字列 - - - - - - - - - - - - - - - - - - - - - - - - - - -9
レイアウトグローバル
配列
シーンのパブリック情報 - - - - - - - - - - - - -50
- - - - - - - - - - - - - - - - - - - - - - - - - - - -9
- - - - - - - - - - - - - -50
- - - - - - - - - - - - - -10
インデプスのオブジェクト - - - - - - - - - - -52
ベクトル - - - - - - - - - - - - - - - - - - - - - - - -11
リクエスタインタフェースの拡張 - - - - - -54
ポイントID/ポリゴンID - - - - - - - - - - - - - -11
アーキテクチャの詳細
nil - - - - - - - - - - - - - - - - - - - - - - - - - - - - -11
LS/IF(イメージフィルタ)
新バージョンでの変更点
プロセスID
- - - - - - - - - - - - - - - - - - - - - -12
LScriptのオブジェクトエージェント - - - - -12
- - - - - - - - - - - - - -55
- - - - - - - - - -55
イメージバッファの選択
- - - - - - - - - - - - - -56
イメージバッファの処理
- - - - - - - - - - - - - -57
イメージデータのキャッシュ化
–目次i–
- - - - - - - - -58
LS/IFロジックの流れ - - - - - - - - - - - - - - - - -58
モニタの使用
BobObjの実験 - - - - - - - - - - - - - - - - - - - - - -82
- - - - - - - - - - - - - - - - - - - - - -59
プラグイン間通信 - - - - - - - - - - - - - - - - - -83
LS/PT(プロシージャルテクスチャ) - - -59
適格データタイプ - - - - - - - - - - - - - - - - - - -85
シェーダー関数 - - - - - - - - - - - - - - - - - - - - -60
Macintoshに関するLScriptの注意事項
テクスチャの処理 - - - - - - - - - - - - - - - - - - -60
ShaderObjectメソッド - - - - - - - - - - - - - - - -61
LScriptプリプロセッサ
LS/DM(ディスプレイスメントマップ) -62
LS/IA(アイテムアニメーション)
- - -86
- - - - - - - - - - - - - -86
LScriptプリプロセッサ - - - - - - - - - - - - - - - -86
- - - - -62
コンパイラディレクティブ - - - - - - - - - - - - -86
モーションの処理 - - - - - - - - - - - - - - - - - - -62
Preprocessor Macros - - - - - - - - - - - - - - - - -89
LS/OR(オブジェクトリプレイスメント) 63
High Visibility - - - - - - - - - - - - - - - - - - - - - - -89
LS/GN(レイアウトジェネリック)
ジェネリックスクリプトの構築
- - - -63
Ver.2.0での変更点 - - - - - - - - - - - - - - - - - -90
- - - - - - - - -64
リビジョン履歴 - - - - - - - - - - - - - - - - - - - -99
ジェネリック関数 - - - - - - - - - - - - - - - - - - -64
ベータ 7: - - - - - - - - - - - - - - - - - - - - - - -99
LScriptの拡張:ネイティブコードとのリンク 65
ベータ 6: - - - - - - - - - - - - - - - - - - - - - - -99
メッセージの表示 - - - - - - - - - - - - - - - - - -66
ベータ 5:LScript v2.0 ベータ 5
LScriptへのエクスポート関数 - - - - - - - - -69
ベータ 4: - - - - - - - - - - - - - - - - - - - - - -102
Makefileの使用 - - - - - - - - - - - - - - - - - - - -69
共有ライブラリの使用
ベータ 3: - - - - - - - - - - - - - - - - - - - - - -103
- - - - - - - - - - - - - -70
ベータ 2: - - - - - - - - - - - - - - - - - - - - - -105
LScript共有ライブラリの拡張 - - - - - - - - - -71
"lscript.h"への拡張
索引 - - - - - - - - - - - - - - - - - - - - - - - - - - -107
- - - - - - - - -71
複数のインスタンスのハンドリング
BobObjシェル
LScript最新情報について - - - - - - - - - - - -105
- - - - - - - - - - - - - - - - -71
プライベートクラスメソッド
- - - - - - -99
- - - -73
- - - - - - - - - - - - - - - - - - - -74
オブジェクトエージェントの共有ライブラリの作成
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -81
–目次ii–
LScriptの概要
LScriptの実行
LScript(エル・スクリプト)はNewTek社のLightWave用に特
LScript Scripting Pluginを起動すると、ファイル選択ダイアロ
別に設計されたスクリプティング・プラグインです。
グボックスが現れます。最初にLScriptスクリプティングプラ
スクリプトのプログラミングは初めてという方や、また
グインを起動した場合、このダイアログボックスには使用し
Amiga版LightWaveの時代から AREXXをお使いになっている
ているモデラー・コンフィギュレーションファイル
方も、LightWaveスクリプトをプログラムする方にはLScript
(LWM.CFG)により指定されたプラグイン・ディレクトリが
はたいへん便利なものです。すでに使用できるLScriptsの実例
表示されます。次にプラグインを呼び出した場合は、最後に
が豊富にありますから、本章をお読みになる前にそれをお試
選択したスクリプトを呼び出したディレクトリが表示されま
しください。また、CやC++といった一般的なプログラミング
す。
言語での経験があれば、LScriptの全体構造はすぐにご理解い
ファイル選択ダイアログを使うと、実行するLScriptファイル
が入っているディレクトリを表示することができます。スク
ただけるでしょう。
リプトを選択すると、LScriptは、そのスクリプトをコンパイ
ル し、コンパイル中にエラーがなければ、続いてスクリプト
を実行します。
LScriptスクリプティングプラグインはまた、プラグインサー
バーとしても機能しますから、スクリプトを直接Customメニ
ューに追加することが可能です。その後、LScript項目を選択
すると、選択されたスクリプトでLScriptスクリプティングプ
ラグインが実行されます。LScriptをCustomメニューに追加す
るには、 C u s t o mメニューにあるビルトインコマンドC o n f i gure Listを使うか、添付のLScript listadd.lsを実行してください。
サーバーに関連する項目をこの方法でCustomメニューに追加
した場合は、かならずそれらをファイルに保存してください。
こうしておけば、開始するたびにLightWaveモデラーがカス
タムマクロを自動的に再ロードします。この機能の詳細につ
いては、本マニュアルの『LightWaveモデラー』の章をご覧
ください。
–1–
本章で使用する書式
void
本ユーザーガイドのこれ以降のセクションでは、次のような
識別子を使って各コマンドの呼び出し構文を表現します。次
戻り値を持たない場合、または受け取るパラメータがない場
に、それぞれの意味をまとめます。
合。
数値
型[#]
小数値を含む数値データ型。また、符号インジケータと指数
各タイプのデータ型の " # "個のエレメントに対する配列参照
指定子を処理できます。
("#"がなければ、可変サイズ)
整数
[]
小数部の値なしとして書かれる数値データ型。また、符号イ
関数のオプション引数で、省略可能なものです。
ンジケータを処理できます。
<データ型>
文字列
上記のデータ型の単一インスタンス
連続した A S C I I文字列からなるデータ型。二重引用符(")で
囲みます。
status
コマンドのエラーステータス(autoerrorプラグマが使われて
ベクトル
いない場合、これが使われていればケースエラーは捕捉され
山形カッコ(<>)で囲み、カンマで区切った3つの数値(例:
て実行が停止します。
)
<15,34,5.34>)からなるデータ型。
ブール
ポイントID
TRUE/true/!0(真)またはFALSE/false/0(偽)
ポイント識別子
本書で使用する書体
ポリゴンID
ポリゴン識別子
,,,
上記データ型をカンマで区切り、複数並べたもの。または、
単一のデータ型の複数を表現したもの。
–2–
明朝体
解説などの本文に使用します。
ゴシック体
重要事項などに使用します。
monospace
LScriptスクリプト本文に使用します。
下線
スクリプトに対する注釈に使用します。
function
LScriptの関数名やキーワードに使用します。
LScriptの内部
これからのセクションでは言語構文、変数、コントロール構
ワードで開始し、終了カッコの代わりにキーワードで終わる
造、コマンドおよび関数を確認しながら、LScriptの詳細を見
構文を用いることもできます。
ていきます。
ユーザー定義プロシージャは、1つまたは複数の引数を受け取
LScriptスクリプトの構造
ることができます。プロシージャ名の次にコロン “:” を付け
LScriptは、 Cプログラムの構造によく似ています。スクリプ
てから、これらの引数の宣言をします。
トには、プロシージャが必要です。またその数はいくつでも
ユーザー定義プロシージャにはまた、リターンコマンドを使
かまいません(使用しているコンピュータのメモリ量により
って1つまたは複数の値(戻り値)を呼び出し側に返す機能が
制限されます)。1つにした場合は、文頭に "main" とラベル
あります。リターンコマンドは、2つまたはそれ以上の値をカ
を付けてください。
ンマ“,”で区切って返すことができます。ユーザー定義関数
が複数の値を返す場合は、受け取り側の変数を配列タイプと
main
しておくと良いでしょう。しかしLScript言語ではこのことは
{
強制しませんから、受け取り側変数が配列でない場合は最初
・・・
の戻り値が割り当てられ、残りの値は破棄されます。配列タ
}
イプの変数が使用されるときも、ユーザー定義プロシージャ
で返す引数の数と同じ大きさである必要はありません。その
mainプロシージャ
位置が配列サイズを越える戻り値は、単に破棄されるからで
LScriptの実行は、つねに main()プロシージャによりコント
す。
ロールされています。スクリプト内のすべての処理は、この
一例としてユーザー定義関数を作成してみましょう。最初の
プロシージャの中で行われます。また main()プロシージャ
引数が0ではないなら特定の値を選択し、最初の引数が0に等
を使って、スクリプトに属している他のプロシージャを選択
しいと判断したら他の値を選択する関数を作ります。次のよ
して実行することもできます。こうしたプロシージャは、ビ
うに書いて、新規のプロシージャを呼び出すことができます。
ルトイン(LScriptスクリプティングプラグインにとって内部
のもの)の形を取ることができますし、だれもが定義できる
スクリプティングプロシージャとすることもできます。こう
した外部スクリプティングプロシージャはユーザー定義プロ
シージャと言われます。
ユーザー定義プロシージャ
ユーザー定義プロシージャは、そのプロシージャの名称を宣
言することによりスクリプト内で作成できます。その後に開
始カッコ“{”を付け、プロシージャの終わりには終了カッコ“}”
を付けます。別の方法としては、開始カッコの代わりにキー
–3–
main
library "mylib.lib";
{
{
・・・
・・・
t = which(val1,val2,val3);
}
・・・
}
添付のLScript file2.lsは、LScriptライブラリ機能の良い例です。
which: v1,v2,v3
ライブラリファイル( file2.lib)をロードすると、このタスク
{
が実行できます。ライブラリファイルには、任意の名称を付
if(v1)
けられます。ライブラリに関してLScriptでは、名称に関する
return(v2);
規約はありません。
else
ライブラリのファイル名に2バイト文字(漢字、ひらが
return(v3);
な、カタカナなど)を使用しした場合は、正常に動作
}
しない可能性があります。
LScriptではまた、各スクリプトが実行されるとき自動的にロ
ライブラリ
ードされるデフォルトライブラリを指定することができます。
ユーザー定義プロシージャは、LScriptライブラリに保管でき
ます。LScriptライブラリはLScriptsのスクリプトとよく似て
いますが、 main()関数を含んでいないことと、グローバル
変数を宣言できないことが違います。
スクリプトでライブラリを処理するように命令する場合は、
ライブラリ指示語を使います。ライブラリ指示語を与えられ
ると、LScriptは主スクリプトにある未解決の参照を満たすユ
ーザー定義プロシージャを指定されたライブラリ内で検索し
ます。未解決の外部参照を満たすユーザー定義プロシージャ
のみが、スクリプトの実行用ランタイムスペースにロードさ
れます。LScriptは、スクリプトに関係のないそのほかのライ
ブラリ・プロシージャは無視します。(loadallプラグマ指
示語を使うとこの動作は変更できます。これについては本章
の別の箇所で説明します。
)
ライブラリコマンドはグローバルレベルで(つまり宣言した
関数の外部で)スクリプトに指定して、ライブラリファイル
の名称をそれに続ければライブラリにアクセスできます。以
下に例を挙げます。
–4–
LScript言語の構造
LScript内のコメント
標準的なC/C++構文を使うと、LScriptsにコメントを埋め込む
言語で使うキーワード
ことができます。C + +で標準的なダブルスラッシュを使うと、
次の表に、 LScript言語で使うキーワードをまとめます。Cま
1行のコメントを付けられます。
たはC++ のプログラミングの経験のある方ならば、多くのキ
jitter(1.5);
ーワードはすでにご存知のものだと思います。数はごく少な
//見苦しくする
いとはいえ、ここで各キーワードを詳細に説明することは本
またCで標準的な"/*" "*/" 記号の対を使うと、複数行のコ
章の範囲を超えています。制御構造を説明するこれ以降のセ
メントを付けることができます。
クションで、いくつかのキーワードについて説明しています。
次に掲載した演算子は、Cプログラミングの基本マニュアルに
/*
複数行
はかならず掲載されているものです。
の
L S c r i p tのCスタイルの構文では、次のキーワードおよび演算
コメント
子が使われます。
*/
if
else
while
pragma
var
break
switch
case
library
const
continue
return
True/true
False/false Nil/nil
=
+
-
*
/
==
!=
<=
>=
+=
-=
*=
/=
++
--
||
&&
!
%
&
^
<<
>>
|=
^=
コメントとして、2バイト文字(漢字、ひらなが、カタ
カナなど)を使用した場合、LScript実行中にエラーが
発生する場合があります。
&=
LScriptではまた、スクリプトの構築に次のようなAREXXスタ
イルのキーワードを使うことができます。
begin
end
then
do
to
select
when
by
この2つ目の構文は、LScriptのスクリプト例、file2.lsでも使
われています。
–5–
LScriptの制御構造
とができます。このセクションでは、その制御構造について
else節を使うと、 if演算子が"either/or"条件を扱うことがで
きるようになります。 else節は if演算子の実行可能文(ま
説明します。
たはブロック制御)に続けます。
LScriptには制御構造があり、構造化プログラムを設計するこ
if(lensFlare[index])
if/else
{
if演算子を使うと、LScriptは実行すべきものを判断できるよ
file.writeln("LensFlare 1");
うになります。この演算子では異なる2つのスタイルの構文を
・・・
サポートしています。第1のスタイルはC言語と同じものです。
}
if ((f.eof() == false) && (size(tokens) > 1)
else
&&(tokens[1] == "Plugin"))
file.writeln("LensFlare 0");
info(tokens[1]," ",tokens[2]);
2つ目のスタイルはAREXXと同じです。
while
while演算子を使うと、LScript内でループを使用できるよう
if f.eof() == false and size(tokens) > 1 and
になります。文が1つの制御ブロック内にあり、条件が論理上
tokens[1] == "Plugin" then
のtrue(真)である限り、1つまたは連続する複数の文を実
info(tokens[1]," ",tokens[2]));
行します。この制御は次のような形をとります。
if演算子が複数の実行可能文を含む場合は、文を1つの制御
while (ブール表現)
{
ブロック内に納めなければなりません。これは、ユーザー定
義プロシージャが使う構造と同じです。
文1;
if (file == nil)
文2;
{
•
error("Cannot create scene file
•
",sceneFile);
文n
return;
}
}
L S c r i p tでは、スクリプトのプログラマは i f の場合と同様に
AREXXの場合は、次のようになります。
whileでも、AREXX風の構文を使うことができます。
if file == nil then
while ブール表現 do
begin
begin
error("Cannot create scene file
文
",sceneFile);
end
return;
スクリプトプログラマがループの流れを変えるためのLScript
end
コマンドに、 breakおよびcontinueの2つのコマンドがあ
–6–
ります。このコマンド各々ついては、本ドキュメントの後の
switch (式)
{
セクションで説明します。
case 定数式1 :
for
文;
break;
whileと同様に、for演算子を使ってもループ制御をLScript
内で使うことができます。 whileの場合はループ構造の制御
に制限があり、条件式の評価のみを実行できますが、 for演
case 定数式2 :
文;
break;
算子では、ループ条件の評価に加えてループに先立つ初期化
と、ループ後のコードの実行ができる点が異なります。Cバー
•
ジョンのforは次のような形になります。
•
for (カウンタの初期化 ;条件判定 ; カウンタの再設定)
{
case 定数式n
文;
break;
文1;
文2;
default:
•
文;
•
break;
文n
}
}
この場合もLScriptには、select演算子というAREXX風バー
LScriptではまた、次のような簡潔でAREXX風のfor演算子の
ジョンの選択機構があります。ただし、選択基準が数値だけ
形も許されます。
に限定されている switch演算子とは異なり、 select 制御
では式全体が評価され、実行するコードを決定します。
for 変数 = /expr/ to /expr/ [ by /expr/ ] do
begin
select
文
when 式 then do
end
文
end
どちらの形式の場合も、 forループ演算子が使う変数は使用
end
前に宣言されている必要があります。
switch, select
?,: (インライン選択)
LScriptはスクリプトプロクラマに、構造化された選択機構を
インライン選択演算子 "?",":"を使うと、2つの選択項目の
提供します。これは、Cにおける同様の機能と同じものです。
なかから条件に基づいて1つを選択できます。 select演算子
switch演算子を使うと、コードの実行を、式の数値にもと
のこの省略形式は、C言語で提供されているものと同じです。
づいて選択できるようになります。
次のような形になります。
ブール式 ? 真の場合 : 偽の場合
–7–
この演算子は、LScript内で式を使えるところなら任意のとこ
ドはgotoコマンドによく似ていますが、 gotoコマンドの場
ろに配置できます。
合は移動位置は制御ループの冒頭になります。
whileの場合、制御ループの判断の基準となる条件は再度評
例
価されて、プログラムの実行はそこから継続します。
main
forループの場合はループの後にあるコードが評価され、制
{
御ループの判断の基準となる条件も再評価されます。プログ
var j = 1;
ラムの実行は、そのポイントから継続します。
・・・
info("return is",(j == 1 ? "yes" :
while (1)
"no"));
continue;
}
break
前述のbreakコマンドは、LScript内のループ制御を途中で終
了するものです。 w h i l eまたは f o r 演算子がその実行中に
b r e a kに遭遇すると、すぐにそのループ制御の終端の次の
LScript文に移行します。
例
while(j)
{
if(j == 10)
break;
++j;
4行目
info("j == ", j);
7行目
}
この例では4行目にあるbreakまで来ると、LScriptはwhile
ループを終了して 内部プログラムカウンタを7行目 info()
の実行可能文に設定します。
continue
continueも、LScript内のループ演算子の実行の流れを変化
させるコマンドです。 breakの場合、プログラムの実行はル
ープの次に続く LScriptコード行に移動して継続します。一方
continueコマンドの場合は、ループ演算子が制御ループの
終端に達したときのように振る舞います。 continueコマン
–8–
//これは無限ループになります
LScriptのデータ型
LScriptは、さまざまなタイプのデータをサポートしています。
たとえば二重引用符は、定義する文字列リテラルの開始と終
これらのタイプについて、ここからのセクションで説明しま
了を示す記号です。1つまたは複数の二重引用符を文字列内に
す。
入れて表示するにはどうすればよいでしょう。LScriptのコー
ド行を次のようにすると、エラーにはなりませんがなにも表
数値
示されません。
LScript内の数値は正負のいずれにもなれますし、浮動小数点
quoteString = ""I don’t like this", he
said";
値を表すために小数点を入れることもできます。LScriptは絶
対値表現もサポートします。
LScriptは最初の2つの二重引用符を、変数 quoteString に
main
割り当てる文字列リテラルの開始点と終了点と解釈します。
{
その後LScriptの処理は、表示したい文字列の最初の文字から
var integer = 15;
継続します。これではどうしようもありません。
var real = 0.3;
文字列内の引用符は、LScriptに特殊文字として無視させなけ
var negative = -35.356;
ればなりません。次のようにすると、これらをエスケープで
var scientific = 7.5E+13;
きます。
・・・
}
quoteString = "\"I don’t like this\", he
said";
文字列
文字列リテラルは、文字列の前後に二重引用符 (")を付けて
配列
表します。
LScriptは、10次元までの配列をサポートしています。配列要
LScripではC言語のように、文字列内の特定の文字を"エスケ
素は、 サポートしているものならLScriptデータ型(配列はネ
ープ"つまり拡張表記できますし、またそうしなければならな
スト不可ですから配列は除く)すべてを保持できます。各配
い場合があります。ある文字をエスケープすると、LScriptは
列には、これらのデータ型をどのように混在させてもかまい
その文字をリテラルとして、つまり定義する文字列の一部と
ません。
して特殊な意味を付けずに扱います。文字をエスケープする
配列は、2つの異なる形式で作ることができます。最初の形式
には、LScriptに処理させたい文字の直前に¥マーク(¥マー
では、配列を単に宣言して配列を含む要素の数を示します。
クは英文フォントでは \(バックスラッシュ)となります。)
main
を入れます。
{
main
var check[15];
{
・・・
var astring = "Here is a test string";
}
・・・
}
–9–
このやり方で配列を宣言すると、新規の配列内の要素それぞ
main
れは内部的に未初期化とマークされます。この状態の要素は、
それに値を割り当てるまでは使えません。LScriptが未初期化
{
var check[15];
状態の配列要素つまり変数へのアクセスを検知すると、エラ
check[] = -1;
ー・メッセージを生成します。
//15個の要素すべてに-1'を入れる
次の初期化形式を使うと、ディスクファイル内のエントリか
・・・
ら配列を宣言して初期化できます。このディスクファイルに
}
は、1行に1つの配列要素(数値または文字)が入らなければ
なりません。またこれは、ASCIIテキストフォーマットでなけ
新バージョンでの変更点
ればなりません。各エントリを読み込むたびに、LScriptエン
新しいバージョンのインタプリタでは、1次元(または"リニ
ジンがデータ型を判断します。
ア")配列は明示的に宣言する必要はなくなりました。配列の
配列のサイズを示す数値パラメータの替わりに文字列リテラ
要素は、"要求に応じて"配列内に割り当てられます。つまりま
ル値を使うと、ディスクファイルからの配列が初期化されま
だ存在しない配列内の特定の要素にアクセスする場合は、自
す。
動的に既存の配列を拡張して新しいサイズにします。
main
配列は"急遽"作られたのですから、明示的に宣言された配列を
{
使って関数の戻り値を入れるといった状況では、期待通りに
var points["\\home\\rbh\\points.txt"];
は動作しないことにご注意ください。
・・・
次のサンプルコードをごらんください。
}
main
{
配列が宣言されると、配列要素を直接参照することで個々の
要素にアクセスできます。L S c r i p t内では、配列要素はCまた
はC++のようにオフセット(0)からではなく、Pascalの場合
var firstItem;
3行目
firstItem = parse(" ","Hello there,
と同様にオフセット(1)からアクセスされます。使用するコ
everybody!");
5行目
ンピュータで使用可能なメモリ容量による制限以外には、各
if(firstItem == "Hello")
6行目
・・・
LScriptで使える配列の数に制限はありません。
}
整数値として評価される式はすべて、配列インデックスとし
て使うことができます。たとえば次のようになります。
p a r s e ( ) を呼び出すと H e l l o , t h e r e ,および e v e r ybody!という3つの項目が返されます。以前のバージョンで
は最初の項目( "Hello")だけが、変数 firstItemに割り当
randElement= points[random(1,size(points))];
空のインデックスを使って値を配列に割り当てれば、1つの値
てられます。
を使って1つのステップでL S c r i p t配列全体を初期化すること
firstItemは作成されたとき、配列として明示的に宣言さ
ができます。
れていないからです。よって、これが保持できる値は1つだけ
–10–
になります。 p a r s e ( ) からの残りの値( t h e r e および
ベクトルデータ型の個々の要素を宣言すると、キーワード x、
"everybody!)は、単に破棄されます。
yおよび zを使ってアクセスできます。たとえば次のようにな
しかし新しいバージョンでは、配列はインタプリタにより必
ります。
要なときに自動的に作られます。ですから新バージョンでこ
main
のコードを処理すると、3つの要素からなる配列が自動的に生
{
成されて firstItemに割り当てられます。ご覧のように上
var apoint = <4.5,10,.03>;
記の6行目は、新バージョンでは正しくありません。
++apoint.x;
firstItemは、ここでは3つの要素を持つ配列だからです!
--apoint.y;
この新しい動作に対応するには、6行目を次のように変更しま
if(apoint.x > 4)
す。
if(firstItem[1] == "Hello")
・・・
6行目
}
またさらによい解決法は、 firstItemを結合割り当ての"カ
ッコ"で囲みます。そうすると、5行目は、前バージョンと同
ポイントID/ポリゴンID
様に動作します。
この2つのデータ型は、L S c r i p tが直接使えるわけではありま
(firstItem) = parse(" ","Hello there,
せん。
everybody!");
これらを L S c r i p tに含めると、 a d d p o i n t ( ) や a d d p o l y-
gon()といったモデラー固有関数の戻り値をサポートできる
複数次元の配列は、キーワード varを使って明示的に
ようになります。変数および配列も、このデータ型となりま
宣言しなければなりません。
す。
ベクトル
nil
L S c r i p tのベクトルタイプは、3つの数値からできています。
nilはLScriptにおいて、条件でもありデータ型でもあります。
各数値はカンマで区切り、山形カッコ" <>"で囲みます。この
変数および配列要素にこの値が割り当てることができますし、
データ型は、多くのビルトインLScriptやモデラー関数へ渡す
この値を持つかどうかも検査されます。この値はまた特定の
ことができます。またユーザー定義プロシージャへ、プロシ
LScriptビルトインコマンドにより返され、ある種の失敗を表
ージャ引数として渡すことができます。LScriptコマンドには、
示します。たとえば、オブジェクト作成コマンド file()は、
ベクトルデータ型を返すものがあります。
ファイルオブジェクトを作成できないとnilを返します。
配列の初期化にこの値を使うとよいでしょう。この値で初期
main
化しておけば、未初期化の配列要素にアクセスしたときにお
{
こるランタイムエラーを避けることができます。
var apoint = <4.5,10,.03>;
・・・
}
–11–
main
LScriptのオブジェクトエージェント
{
L S c r i p t環境にはビルトインのオブジェクトが含まれていて、
これをオペレーティングシステムレベルの関数およびデータ
var check[15];
check[] = nil;
型へのインターフェイスとして使うことができます。オブジ
・・・
ェクトエージェントといわれるこれらの内部オブジェクトつ
いて、このセクションで説明します。
}
parse()のような変数戻り値を持つLScriptコマンドを扱う
場合は、配列をnilに初期化するとよいでしょう。
ファイルオブジェクト
LScriptファイルオブジェクトエージェントは、オペレーティ
ング・システムのファイルシステムへのアクセスを提供しま
プロセスID
す。LScriptのビルトインコマンド File()は、このタイプの
ポイント I Dやポリゴン I Dの場合と同様に、このデータ型も
オブジェクトを返します。変数に割り当てられると、次のよ
LScriptから直接利用はできません。これをLScriptデータセッ
うなさまざまなファイルオブジェクトエージェントメソッド
トに入れると、 spawn()、wait()およびterminate()
に、ホスト変数からアクセスできます。
の各制御コマンドの処理をサポートできます。
isOpen
そのファイルが開いていてアクセス可能なことを示す論理値
を返します。
isOpen (void)
open
新規ファイルを指定されたモードで開きます。新規に開かれ
たファイルは、既存のファイルオブジェクトエージェントに
割り当てられます。
void open(ファイル名,モード)
ファイル名:
文字列; 開くファイルのファイル名
モード:
文字列; 開くために使用するモード
reopen
すでに開いているファイルを閉じて、それを指定されたモー
ドでもう1度開きます。
void reopen(モード)
モード:
–12–
文字列; ファイルを開くために使用するモード
close
read
すでに開いているファイルを閉じます。
ファイルからテキスト行を1つ読み込み、それを文字列として
返します。ファイル がバイナリモードで開いている場合、こ
void close(void)
の関数は無効です。
eof
read(void)
そのファイルがE O Fマーカーに達したかどうかを示す論理値
返す値:
文字列; ファイルからのテキスト行
(TRUE/FALSE)を返します。
readNumber
eof(void)
返す値:
ASCIIモードの場合、この関数は文字シーケンスをファイルか
ブール; trueまたはfalse
ら読み込み、それを1つの数値に変換します。バイナリモード
の場合、1つの整数値がファイルから読み込まれます。
rewind
ファイルの読み込み/書き出しポイントをファイル冒頭に再
readNumber(void)
設定します。
返す値:
rewind(void)
返す値:
数値 浮動小数点値または整数値
readVector
文字列
ASCIIモードの場合、この関数は文字列をファイルから読み込
すでにひらいているファイルの名称、あるいはそれがもとも
み、それをベクトルデータ型として返します。ファイル内の
と指定されている場合はパス が入っている文字列を返します。
データは空白で区切った浮動小数点値でなければなりません。
バイナリモードの場合、サイズのdouble型の3つの数値が読み
ファイルの名称
込まれ、ベクトルとして返されます。
write、writeln
readVector(void)
w r i t e ( )は、1つまたは複数の引数をファイルに入れます。
writeln()はwrite()と同じですが、復帰改行文字を行末
返す値:
にアペンドします。
ベクトル ファイル内にあるままのベクトル
parse
ファイルがバイナリモードで開いている場合は、これらのコ
ファイルから1行読み込み、その行のトークンを表す複数の要
マンドは無効です。
素を返します。トークンは、文字列引数で提供する文字のう
ち1つによって区切られます。 この関数は、バイナリモード
write(アイテム1[,アイテムn])
アイテム:
返す値:
では無効です。
1つまたは複数の変数または定数
整数; ファイルに書かれるバイト数
parse(トークン)
–13–
トークン:
文字列; トークンセパレータの文字列の1 文字
返す値:
文字列; トークンを表している文字列の配列
nl
readByte
復帰改行文字をファイルに書き込みます。このコマンドは、
ASCIIモードでは、この関数はテキストファイルから文字を1
バイナリモードでは無効です。
つ整数値として返します。バイナリモードでは、u n s i g n e d
charサイズのバイナリ値1つがファイルから読み込まれ、整数
void nl(void)
値として返されます。
linecount
readByte(void)
ファイルがASCIIモードで開いている場合、この関数はそのと
返す値:
整数; ファイルの1バイト
き開いているファイル内のテキスト行数を返します。しかし
バイナリモードでは、バイトで表したファイルサイズを返し
writeNumber
ます。
ASCIIモードの場合、与えられた値がテキスト・ファイルに浮
動小数点値として文字形式で書き込まれます。バイナリモー
linecount(void)
返す値
ドの場合、double型のバイナリ値1つがファイルに書き込まれ
整数; ファイルの行数またはバイト数
ます。
line
writeNumber(値)
ASCIIモードの場合で引数がなにも与えられていなければ、こ
値:
浮動小数点値
の関数はそのファイル内のそのときの行番号を返します。フ
返す値:
整数;ファイルに書き込まれるバイト数
ァイル内のテキスト行数の範囲内に収まる整数値が与えられ
ると、ファイルポインタをその行番号まで移動します。
writeInt
このコマンドは、バイナリモードでは無効です。
ASCIIモードの場合、与えられた値がテキスト・ファイルに整
数値として文字形式で書き込まれます。バイナリモードの場
line()
返す値:
合、サイズの整数型のバイナリ値1つがファイルに書き込まれ
整数; オプションのパラメータが省略された場合、
ます。
現在の行番号
line(整数)
writeInt(値)
整数:
移動する行番号
値:
整数;書き込まれる値
返す値:
整数; ファイル内で移動する行番号
返す値:
整数;ファイルに書き込まれるバイト数
readInt
writeByte
ASCIIモードの場合、この関数はテキストファイルから文字列
ASCIIモードの場合、与えられた整数値がテキスト・ファイル
を読み込み、整数データ型を1つ返します。バイナリモードで
に文字として書き込まれます。バイナリモードの場合、与え
は、サイズの整数型のバイナリ値1つがファイルから読み込ま
られた値はファイル内にunsigned charサイズのバイナリ値1
れます。
つとして格納されます。
readInt(void)
返す値:
writeByte(値)
整数; ファイルの整数値
–14–
値:
整数;書き込まれる値
返す値:
整数;ファイルに書き込まれるバイト数
offset
ビルトイン関数
このメソッドがパラメータなしで呼び出されると、そのとき
アーキテクチャに関係なく、各LScriptはLScriptエンジンにビ
のファイルのオフセットのバイトを返します。整数値を与え
ルトインされている属性にアクセスできます。こうした"ビル
ると、ファイル内でメソッドと相対的に指定したオフセット
トイン"には、あらかじめ定義された値、コマンドおよび関数
にファイルポインタを移動できます。 offsetメソッドには、
があります。ユーザー定義変数を使う任意の場所で、これら
次のオプションがあります。 FROMSTARTは、ファイル冒頭
の定数を使うことができます。しかし、その値は変更できま
を起点に移動します(これはメソッドが指定されていない場
せん。つまり文の左辺には使えません。
合のデフォルトです)。FROMENDは、ファイル終端を起点に
移動します。 FROMHEREでは、与えられたオフセット値をポ
事前定義値
インタの現在の位置と相対的位置と解釈します。
各LScriptで使用できる定常(つまり読み込み専用)変数がた
くさんあります。その中には、モデラーコマンドに直接関係
offset([値[,メソッド]])
値:
整数;使用されるオフセット
するものもいくつかあります。これを次にまとめます。
メソッド:
定数;FROMSTART,FROMEND またはFROMHERE
PI
E
GAMMA
DEG
返す値:
整数;ファイル内での現在のオフセット
PHI
READ
WRITE
APPEND
LScriptファイルオブジェクトを使ったさまざまな例について
VERTICAL
HORIZONTAL
FROMSTART
FROMEND
は、 添付のLScriptスクリプトの例をご覧ください。
FROMHERE
INTEL
ALPHA
SGI
MIPS
MACINTOSH
AMIGA
CREATE
ATTACH
AUTOCLEAR
LAYOUT
MODELER
SCREAMERNET nil
true/TRUE
false/FALSE
X
Z
ユーザー作成のオブジェクトエージェント
LScriptでは、ユーザーが独自のオブジェクトエージェントを
作ることができます。これを利用するために必要なサポート
事項およびステップについては、「LScript共有ライブラリの拡
Y
LightWaveモデラーのもとで使うように設計されたスクリプ
張:ユーザー定義のオブジェクトエージェント」で説明して
トには、そのために事前に定義された値を持っています。次
います。
にそれをまとめます。
–15–
GAUSSIAN
UNIFORM
NORMAL
SHARP
BUFFERED
KNOTS
SUBTRACT
INTERSECT
ADD
LENGTHS
CORE
TUNNEL
STENCIL
SLICE
FLAT
SMOOTH
METAFORM
SET
CLEAR
VOLUME
CONNECT
NPEQ
NPLT
NPGT
VOLEXCL
VOLINCL
SURFACE
NVEQ
NVLT
NVGT
CURVE
NONPLANAR
SELECTED
FACE
UNSELECTED
ABORT
START
END
DETAIL
GLOBAL
内部コマンド
USER
RADIAL
UNION
POLYNDX
LScriptには、多くの一般的なビルトインコマンドがあります。
POLYID
POINTNDX
POINTIDPOINTNDX
但しこれらの関数は、LightWaveのModelerまたはLayoutに直
POINTID
接関係しているわけではありません。その呼び出し構文とそ
LightWave レイアウトスクリプトは、次のような独自のグロ
の使用法を、このセクションで説明します。
ーバル定数値のセットにアクセスできます。
sqrt
SCENEMODE
OBJECTMODE
MESH
LIGHT
この関数は、数値の平方根を計算します。また数値を受け取
CAMERA
BONE
SCENE
POSITION
り、その値の平方根を返します。
RIGHT
UP
FORWARD
ROTATION
この関数は、次のように呼び出します。
SCALING
PIVOT
WPOSITION
例
そして、LightWave レイアウトでの特殊なアーキテクチャも、
・・・
その独自の値を持ちます。
angle = 180;
//180度
varSquare = sqrt(angle);
//角度の平方根を計算する
イメージフィルター
・・・
SPECIAL
LUMINOUS
DIFFUSE
SPECULAR
MIRROR
TRANS
RAWRED
RAWGREEN
RAWBLUE
SHADING
SHADOW
GEOMETRY
DEPTH
RED
GREEN
exp
この関数は、値の指数を計算します。また数値を受け取り、
その値の指数を返します。
BLUE
例
ALPHA
・・・
プロシージャルテクスチャ
v1 = exp(27.5);
NORMAL
COLOR
LUMINOUS
DIFFUSE
SPECULAR
MIRROR
TRANSPARENT ETA
ROUGHNESS
RAYTRACEE
・・・
log
この関数は、数値の対数値を計算します。また数値を受け取
変位マップ
WORLD
り、その数値の対数値を返します。
LOCALL
例
オブジェクト置換
NONE
PREVIEW
・・・
RENDER
v1 = log(347.495);
M o d e l e r特有の定数の詳細については本章後半の L S c r i p tの
・・・
Modeler固有コマンドを説明するセクションを参照してくださ
い。
Layout固有定数の詳細については、本章のLScriptのLayout固
有コマンドを説明するセクションを参照してください。
–16–
sin, asin, cos, acos, tan, atan, cosh, sinh, tanh, sec, cot, csc
random
これらの関数は、ラジアンで表された角度の三角法値を計算
この関数を使うと、L S c r i p tが疑似乱数整数を生成できます。
します。また、ラジアン値を受け取り、その値の演算結果を
また、2つの整数値を受け取り、これら2つの数字(これも含
返します。
む)の間に存在する乱数値を返します。
関数sinh(),tanh()および cosh()は、それぞれの関数の
例
双曲線正弦、双曲線正接、双曲線余弦の値を計算します。
・・・
これらの関数の使い方を次に示します。
triggerFrame = random(20,50);
・・・
例
・・・
sin1 = sin(45);
randu
・・・
この関数は、0と1の間の乱数値を返します。
asin1 = asin(276);
例
・・・
・・・
rad = 0.05 * maxlen * (1 + randu())
abs
・・・
この関数は、数字の絶対値を返します。数字の記号に関わり
なく、この関数の戻り値はつねに正となります。
min, max
例
min()関数は、2つの数値の引数のうち小さい方を返します。
・・・
一方max()は、逆に大きい方を返します。
if(abs(decline) > 30)
例
・・・
・・・
t = min(top,7);
ceil, floor
・・・
ceil()関数は、引数として渡された数値以上で最小の整数
値を返します。floor()関数は、数値パラメータ以下で最大
となる整数値を返します。
例
・・・
c = ceil(45.6);
f = floor(13.3);
・・・
–17–
mod
rad, deg
mod()関数は、最初の数値引数を2つ目の引数で割り、割り
rad()とdeg()の2つの関数は、変換ユーティリティーです。
rad()関数は度数で表現された角度の数値パラメータを1つ
受け取り、それをラジアンに変換します。 deg()関数はラジ
算のモジュロつまり余りを返します。LScript演算子の%を使
っても、この関数を表せます。
アンで表現された角度の数値パラメータ1つを受け取り、それ
例
を度数に変換します。
・・・
t = mod(34.5,6);
例
4.5を返します
・・・
・・・
または
t = rad(degrees);
degrees * (PI / 180) と同等
・・・
・・・
t = 34.5 % 6;
・・・
range
最初の数値パラメータが2つ目と3つ目の数値(これを含む)
で指定された範囲に入っているかどうかを判断します。これ
pow
はブール値(trueまたはfalse)を返します。
pow()関数は、最初の数値引数を2つ目の引数だけ累乗しま
す。
例
・・・
例
if(range(top,3,8))
・・・
t = pow(5,3);
・・・
125を返します
・・・
select
最初の2つの数値パラメータを比較して、第1パラメータが第
hypot
2パラメータよりも小さい場合に、3つ目のパラメータを返し
hypot()関数は、関数の最初と2つ目の数値引数を2辺とす
ます。また第1パラメータが第2パラメータ以上の場合、4つ
る直角三角形の斜辺を計算します。
目のパラメータを返します。
例
例
・・・
・・・
t = hypot(3,5);
t = select(4,7,15,3);
・・・
15を返します
・・・
t = select(15,7,7,10);
・・・
–18–
10を返します
step
例
2つの数値引数を比較して、2つ目の値が1つ目の値よりも小
・・・
さければ0を返します。また2つ目の値が1つ目の値より大き
t = vmag(x,y,z);
いか等しいの場合は、3つ目の数値パラメータを返します。
・・・
与えられた位置のベクトルの大きさ
例
info, warn, error
・・・
t += step(y,10,.25);
これらのコマンドは、サポートされているものであれば任意
0.25でstepします
のデータ型(配列を除く)のパラメータを取り、適切なメッ
・・・
セージタイプをユーザーに表示します。
round
例
小数点以下を四捨五入し整数を返します。
・・・
error("Value ",val," exceeds max limit of ",
例
10 * items," items");
・・・
t = round(37.7);
・・・
38を返します
・・・
file
このコマンドはディスクファイルの位置を表す文字列、また
frac
オプションで、ファイルを開くモードを示す文字列を受け取
数値の小数部を返します。
り、ファイル内のオブジェクトを1つ返します。特定のオブジ
例
ェクトやそのメソッドについては、本章前半のLScript のオブ
・・・
ジェクトを説明しているセクションを参照してください。
t = frac(46.75);
0.75を返します
例
・・・
・・・
var sceneFile = file("\\temp.lws","w");
fac
・・・
fac()コマンドは、与えられた数値パラメータの階乗を計算
ファイルオープンモードは、Cの場合と同じです。次にそれを
します。
まとめます。
例
・・・
t = fac(5);
120を返します
・・・
vmag
vmag()関数は、3次元ベクトルの大きさを計算します。
–19–
r
w
a
b
読込(ASCII)
バイナリ(つまり、"rb"はバイナリで読込)
+
更新(つまり、ファイルポインタは任意に移動可能)
書出(ASCII)
追加(ASCII)
たとえばランダムアクセスのバイナリ読込でファイルを開く
がベクトルのもの、2つのベクトル(定数または変数として)、
には、"rb+"をファイルのオープンモードとして指定します。
第1のベクトルを表す3つの数値と第2のベクトルを表す3つの
オープンモード値オプションが指定されない場合は、デフォ
数値を合わせた6つの数値などを受け取ることができます。
ルトでファイルは読込"r"モード(ASCII)で開かれます。
center()は、ベクトルデータ型を1つ返します。
fileexists
boundingbox()は2点のベクトルを返しますから、その出
力をcenter()に与えることができます。
このコマンドは、特定のファイルの存在を示すブール値
例
(true/false)を返します。
var objectCntr = center(boundingbox());
前述の info(),warn(),error() コマンドと同様にこの
コマンドも、ファイルの名称を評価する文字列を作るための
extent
引数の変数番号を受け取ります。
このコマンドは c e n t e r ( ) の場合と同様、数値/さまざまな
例
タイプの引数を受け取ります。しかし、2つのベクトルの中点
var index = 1;
を計算するのではなく、この2点のエクステント(距離)を返
if(fileexist("\\temp",index,".lwo"))
します。
ファイル名 == "\temp1.lwo"
extent()は、ベクトルデータ型を1つ返します。その要素
(x,y,z)が各軸方向のエクステントを表しています。
・・・
例
filedelete
このコマンドは、指定されたディスクファイルを削除します。
fileexists()と同様に、このコマンドも、ファイルの名
var objectSize = extent(boundingbox());
parse
称を評価する文字列を作るための引数の変数番号を受け取り
parse()は2つのパラメータを受け取ります。最初のパラメ
ます。このコマンドは、実行結果の状態を返します。0が返れ
ータは潜在的トークンセパレータの文字列で、2つ目のパラメ
ば、エラーがなかったことになります。
ータはそれを処理する文字列です。この関数は、文字列(2つ
目のパラメータ)と比較するトークン配列を返します。
例
var index = 1;
p a r s e ( )の戻り値は、データ型配列の変数に割り当てます。
if(filedelete("\\temp",index,".lwo"))
そうしないとデータを失うことになります。
error("Cannot remove
例
file\\temp",index,".lwo!");
var tokens[10];
・・・
var str = "23,45,69.6,100";
tokens[] = nil;
center
tokens = parse(",",str);
3次元空間内の2点が与えられると、このコマンドはその2点
//"23", "45", "69.6"および"100"を返します
の中点を返します。このコマンドは、さまざまなパラメータ
・・・
計数およびタイプを受け取ります。配列内の最初の2つの要素
–20–
size
vector
このコマンドを使うと、特定のデータ型の特定の変数のサイ
このコマンドは文字列引数を受け取り、それをベクトルに変
ズを判断できます。数値の場合は1を返します。ベクトルタイ
換します。
プの場合は3を返します。文字列引数の場合は文字列内の文字
例
数を返し、配列引数の場合は配列内の(配列の全サイズでは
var str = "4 6.5 8";
なく)実際の要素数を返します。
var t;
例
t = vector(str);
var tokens[10];
//<4,6.5,8>を返します
・・・
var str = "23,45,69.6,100";
var t;
string
tokens[] = nil;
このコマンドは、引数の変数番号を受け取り、文字列を構築
t = size(tokens);
//0を返します
tokens = parse(",",str);
//4つの要素を返します
t = size(tokens);
tokens[8] = 1.0;
//4を返します
t = size(tokens);
//5を返します
します。各々の引数には、L S c r i p tがサポートするデータ型
(配列を除く)を含んでいます。
例
t = string("Value ",val," exceeds max limit
of ",10 * items," items");
・・・
split
number, integer
split()は、特にファイルのパス/名称の文字列を処理する
number()は文字列引数を受け取り、それを数値(浮動小数
点)に変換します。 integer()も同じタイプの引数を受け
取りますが、整数値を返します。 integer()の場合、文字
ために作られたものです。これは文字列を受け取り、その文
字列引数からドライブ、パス、ファイルの名称およびファイ
ル名拡張子を表す4つの要素からなる配列を返します。
列内に小数点があればそれは切り捨てます。小数点以下の四
捨五入をするには、round()関数を使います。
例
var str = "69.6";
var t;
t = number(str);
//69.9を返します
t = integer(str);
//69を返します
t = integer(round(number("69.9")));
//70を返します
・・・
–21–
例
例
var file = getfile("Select A
ScreamerNet IIをパラレルで起動します
Scene...","*.lws");
snID = spawn("lwsn -2 ",
if(file == nil)
return;
getenv("TMP"),"\\snii.job ",
if(fileexists(file))
getenv("TMP"),"\\snii.rpl");
{
if(snID == nil)
var base[4];
{
base = split(file);
error("Cannot create ScreamerNet process");
コンポーネントを受け取ります
・・・
・・・
文字列の示すコンポーネント(つまり指定されたドライブ)
がない場合、nilを返します。
append
このコマンドは、文字列および配列のどちらに対しても動作
します。これは LScriptがサポートする任意の整数データ型を、
文字列の最後に文字として追加したり、LScript配列に新規の
要素として追加します。 配列をこの関数を使用する別の配列
に追加することもできます。
spawn
このコマンドは、Windows NTまたはWindows 95環境下で外
部処理の実行を始めます。通常、外部処理の実行はすべてこ
のコマンド内で起こります。この場合 s p a w n ( ) コマンドは、
指定された処理の実行リザルトコードを返します。
しかし、asyncspawnプラグマ指示語がそのスクリプト内で
宣言されている場合は、spawn()コマンドは、成功すると起
動した外部処理の処理IDを返します。
この処理IDは、処理制御関数 wait()やterminate() の引
数として必要となります。
–22–
wait
"Plugins"/PLUGINSDIR
Layout/Modeler
このコマンドは、 s p a w n ( )に同期関数として提供されます。
"Settings"/SETTINSDIR
Layout/Modeler
spawn()の戻り値である処理IDが渡されると、指定された外
代替コンフィギュレーションの位置)
部処理が停止するまでこのコマンドがスクリプト実行を停止
"Content"/CONTENTDIR
Layout
します。そして、その処理の停止時の状況を返します。
"Scenes"/SCENESDIR
Layout
terminate
"Hierarchies"/HIERARCHIESDIR
Layout
コマンドの処理制御用の関数の1つである terminate() は、
"Surfaces"/SURFACESDIR
Layout
指定された処理IDをWindowsに停止させます。
"Output"/OUTPUTDIR
Layout
"Animations"/ANIMATIONSDIR
Layout
terminate(snID);
"Envelopes"/ENVELOPESDIR
Layout
ScreamerNetをシャットダウンします
"Previews"/PREVIEWSDIR
Layout
"Command"/COMMANDDIR
Layout
例
getenv
次のようにすると、これらのディレクトリ値を取得できます。
C言語の getenveと同様に、この関数は環境変数と推定でき
る文字列引数を受け取り、変数のそのときの値を返します。
与えられた名称に対応する変数が環境内になければ、
例
・・・
install = getdir("Install");
getenv()はnilを返します。
・・・
例
plugins = getdir(PLUGINSDIR);
var tempfile =
・・・
string(getenv("TMP"),"\\33j4ks.$$$");
sleep
getdir
次に挙げた定数(文字列リテラル/マニフェスト)について、
sleep()コマンドを使うと、スクリプトをミリ秒(1/1000
秒)で指定した長さ停止し、スリープタイムが過ぎるまでス
getdir()はアプリケーションが使う作業用の値を返します。
クリプト(およびModeler)のWindowsタイム・スライスを
"Fonts"/FONTSDIR
Modeler
解放します。
"Macros"/MACROSDIR
Modeler
"Install"/INSTALLDIR
例
Layout/Modeler
sleep(1000); 1秒スリープします
(LightWaveインストレーション・ディレクトリ)
"Objects"/OBJECTSDIR
Layout/Modeler
"Images"/IMAGESDIR
Layout/Modeler
"Motions"/MOTIONSDIR
Layout/Modeler
"Temp"/TEMPDIR
Layout/Modeler
–23–
dump
サンプル
dump()はデバッグ関数です。これを使うと、スクリプト開
main
発者はすべての内部スクリプト変数とその値を、指定したテ
{
キストファイルにダンプできます。指定したテキストファイ
var heading = recall("heading",15);
ルがすでに存在する場合、この関数が呼び出されると値はそ
var testing = recall("testing",95.34);
のファイルにアペンドされます。
var myName = recall("myName","Bob
例
Hood");
dump("\\myscript.var");
var newName = recall("newName",
string(myName," has no life!"));
dump()コマンドは、ランタイム環境ではサポートされてい
ません。このコマンドが入っているスクリプトは、LScriptコ
info("got heading == ",heading,
ンパイラで正常にコンパイルできます。
", testing == ",testing);
store、recall
この2つのコマンドを使うと、再び呼び出されるまでスクリプ
info("got myName == ",myName,
トが変数値を保持できます。
", newName == ",newName);
store()コマンドはパラメータを2つ取ります。第1のパラ
メータは、格納した値を一意に識別するための文字列リテラ
store("heading",++heading);
ル(または文字列を持つ変数)です。第2のパラメータが、実
store("testing",testing + .5);
際の値です。
store("myName",myName);
r e c a l l ( ) は、 s t o r e ( ) されている値を取得します。
store()の場合と同様に、これも2つのパラメータを受け取
ります。第1のパラメータは、 store()の場合と同様に、値
を保持するときに使った識別子値です。しかしstore()とは
異なり、2つ目のパラメータはその識別子に対して store()
strleft, strright, strsub, strupper, strlower
が発行されたことがあるかどうかを示すデフォルト値を返し
これらの文字列処理関数を使うと、スクリプトのプログラマ
ます。
はLScript文字列を正確に処理できます。
store("newName",newName);
}
strleft()およびstrright()は、文字列の一部を指示さ
れた方向から返します。どちらの関数も2つのパラメータを受
け取ります。第1のパラメータは処理対象の文字列で、2つ目
のパラメータは抽出する文字数を表す数字です。
次の例では"My first name is "Ted""とプリントされます。
例
info("My first name is \"",
strleft("Ted Philmore",3"),"\");
–24–
LightWave Modelerコマンドおよび関数
strsub()も抽出関数ですが、この関数を使うと文字列内の
任意の文字数を、文字列の端ではなく任意の位置から抽出で
本セクションでは、LightWave Modelerに関係したLScriptコ
きます。
マンドと、その呼び出し構文を扱います。
例
本セクションの各コマンドには、コマンドシーケンス ( C S )ま
t = strsub("Ted Philmore",3,3);
たはメッシュデータエディット (MD)という記号が付いていま
"d P"を返します
す。この2つのタイプのオペレーションは別のもので、コマン
ドシーケンスオペレーションをメッシュデータエディットオ
その名称から想像できるように、strupper()と
ペレーション中( editbegin()で初期化、 editend()で
strlower()は与えられた文字列をそれぞれ大文字または小
終了)に実行すると違反になります。LScriptはこうした違反
文字で返します。
操作を検知して、そのスクリプトを終了します。この制約の
どの関数の場合も、与えられたもとの文字列は修正されませ
ないコマンドには、制約なし(IN)という記号を付けます。
ん。
また、LScript1.0以降のバージョンで追加されたコマンド・関
数については、 (CS/1.2)というように、バージョンナンバー
を追記しています。
LScriptがサポートしている特定のモデラーの固有コマ
ンドを詳細に説明することは、本章の枠を超えていま
す。こうしたモデラーコマンドについては、NewTek, Incから
入手できるさまざまなL i g h t W a v eマニュアルで解説していま
す。ここでは LScript言語に関係した各コマンドの呼び出し構
文、および(存在すれば)戻り値を扱います。
autoerrorプラグマが宣言されていない場合、特に注記が
なければLScriptのModeler固有コマンドはステータス値を返
します。このステータス値は、コマンドが返した結果を表し
ています。一般的に、値が0以外の場合はなんらかのエラーを
表すものです。
–25–
new (CS)
load、save (CS)
new()コマンドは、モデラー・システムを完全に初期化しま
load()および save()を使うと、ディスク上のLightWave
す。データを含むレイヤーすべてがクリアされ、内部構造お
オブジェクトにアクセスできます。これらのコマンドは、そ
よび設定が起動時の値にリセットされます。
のとき選択されているフォアグラウンドレイヤー内のデータ
new()コマンドは、ディスプレイ設定(たとえばウインドウ
に対して有効です。
の位置)もリセットするかどうかを示すブールパラメータ
status load(string)
(true/false )をオプションで受け取ります。この指定が
status save(string)
ない場合のデフォルトは、trueです。
void new(リセット)
setlayer、setblayer (CS)
リセット:
setlayer()およびsetblayer()の2つの関数を使うとス
ブール; 画面のリセット
クリプトプログラマは、それぞれフォアグラウンドレイヤー
セーブしていない作業はすべて失われます。またこの
およびバックグラウンドレイヤーのどちらをアクティブにす
コマンドはアンドゥできません。
るかを動的に選択できます。
それぞれの関数は、アクティブとして選択するレイヤーを示
undo (CS)
す整数値の配列またはいくつかの整数値を受け取ることがで
undo()を呼び出すと、オブジェクトに加えた変更をもとに
きます。Ver.5.6までのLightWave Modelerでは、1から10ま
返すことができます。アンドゥできる回数は、L i g h t W a v e-
でのレイヤーが実装されています。
Modelerコンフィグファイル(LWM.CFG)で指定できます。
void setblayer(レイヤー1[,レイヤー2・・・レイヤー10])
void undo(void)
レイヤーn:
delete (CS)
整数; レイヤー番号
void setblayer(layers)
delete()は、そのとき選択されているフォアグラウンドレ
レイヤーn:
イヤー内のポイント/ポリゴン情報をすべて消去します。
整数; レイヤー番号
lyrfg , lyrbg (IN/1.2)
void delete(void)
このコマンドは選択されているレイヤーのナンバーを返しま
cut,copy,paste (CS)
す。フォアグラウンドとしてレイヤーが選択されている場合
このコマンドを使うと、モデラーの内部データクリップボー
はlyrfg()を使用し、バックグラウンドとしてレイヤーが選
ドを管理できます。ほとんどのモデラーコマンドの場合と同
択されている場合はlyrbg()をを使用します。レイヤーナン
様、これらが有効なのは、そのとき選択されているフォアグ
バーは1から10までの値です。
ラウンドレイヤーのみです。
このコマンドが返す値を配列にアサインすることはできませ
んが、配列ではない変数に連続的にアサインすることはでき
void cut(void)
ます。通常、このコマンドは、Lscriptが設定を変える前にユ
void copy(void)
ーザーが選択しているレイヤーを記憶するために使用します。
void paste(void)
スクリプトが終了する時点で、このコマンドによって得た値
–26–
をlyrsetfg()に送る(配列がアクティブなバックグラウン
lyrswap (CS/1.2)
ド情報を保持している場合は lyrsetbg())ことでユーザの
lyrswap()を使用することで、レイヤーの選択状態を簡単
元の設定に戻すことができます。
に反転させることができます。フォアグラウンドレイヤーは
バックグラウンドレイヤーとなり、バックグラウンドレイヤ
lyrfg(void)
返す値:
ーはフォアグラウンドレイヤーとなります。
整数[]; 一つ以上のレイヤーの値
このコマンドはシングルクオート (')キーを押して、レイヤ
ーをスワップさせるのと同じ働きをします。
lyrbg(void)
返す値:
整数[]; 一つ以上のレイヤーの値
void lyrswap(void)
lyrdata,lyrempty (IN/1.2)
lyrsetfg, lyrsetbg (IN/1.2)
これらの関数はともにレイヤーナンバーの配列を返します。
これらの関数は整数の配列、または整数の変数を受け取り、
lyrdataはメッシュデータが含まれているレイヤーナンバー
を返し、 lyremptyは何も含まれていないレイヤーナンバー
複数あるは一つのレイヤーを選択状態にします。LightWave
のモデラーのレイヤーナンバーは1から10まであります。
を返します。
void lyrsetfg(レイヤー1[,レイヤー2・・・レイヤー10])
また、これら関数はレイヤーがフォアグラウンドとして選択
レイヤーn:
整数; レイヤーナンバー
されているか、バックグラウンドとして選択されているか、
あるいは全く選択されていないかにかかわらず、レイヤーの
void lyrsetfg(レイヤー1[,レイヤー2・・・レイヤー10])
値を返します。
レイヤーn:
整数; レイヤーナンバー
lyrdata(void)
返す値:
fixedflex (CS)
整数[]; 一つ以上のレイヤーの値
lyrempty(void)
この関数を使うとスクリプトプログラマは、フレックストラ
返す値:
ンスフォーメーションを呼び出す他のモデラーコマンド用の
整数[]; 一つ以上のレイヤーの値
演算パラメータを作ることができます。こうしたフレックス
コマンドには、twist()およびtaper()があります。
yremptyfg, lyremptybg (IN/1.2)
lyremptyfg() とlyremptybg() はそれぞれ、選択され
fixedflex()は、関数が指定軸に沿った固定範囲で処理が行
ているフォアグラウンドまたはバックグラウンドの空きレイ
われるように、これらのフレックス関数の演算パラメータを
ヤーを返します。
設定します。また、イーズメント "i"(イーズイン)または
"o"(イーズアウト)をフラグを使って指定することもでき
lyremptyfg(void)
返す値:
ます。
整数[]; 一つ以上のレイヤーの値
lyremptybg(void)
status fixedflex(軸,開始点,終点,イーズメント)
返す値:
軸:
定数; X,YまたはZ
開始点:
数値; 度数で表した範囲の開始点
開始点:
数値; 度数で表した範囲の終点
イーズメント:
文字; "i"または"o"
整数[]; 一つ以上のレイヤーの値
–27–
autoflex (CS)
shear (CS)
fixedflex()と同様、この関数はフレックストランスフォ
move()と同様shear()も、選択されたポイントを指定した
ーメーション関数の演算パラメータを修正します。しかしこ
値でオフセットをします。しかし、ポイントの移動は
の関数は、特定の磁極に沿った自動範囲でフレックスコマン
fixedflex()または autoflex()コマンドにより設定さ
ドの演算が進むようにパラメータを設定します。
れたフレックス軸に沿ってのみ行われることにご注意くださ
い。オフセットは、選択されたポイントの中心からの相対距
status autoflex(軸,極性,イーズメント)
軸:
離で、原点からの距離ではないことに注意してください。
定数; X、YまたはZ
極性:
文字; "+"または"-"
イーズメント:
文字; "i"または"o"
void shear(offset)
オフセット:
ベクトルまたは数値;すべての軸に適用されるオフセット値
deformregion (CS)
void shear(xオフセット, yオフセット, zオフセット)
このコマンドは、 vortex()および pole()といった変形関
xオフセット:
数がそのオペレーション中に使う3 D空間領域を確立します。
yオフセット: 数値; Y軸方向のオフセット
zオフセット: 数値; Z軸方向のオフセット
オプションの軸が省略されると、変形は半径で指定した範囲
数値; X軸方向のオフセット
内の全方向に有効となります。軸が指定されると、有効範囲
magnet (CS)
はその特定の軸に沿ったものになります。
magnet()もまた、選択されたポイントに指定された値でオ
フセットするものですが、移動は deformregion()コマン
status deformregion(半径[,中心点[,軸]])
半径:
ベクトルまたは数値; 範囲の半径
中心点:
ベクトルまたは数値; 範囲の中心点
軸:
定数; X、YまたはZ
ドで設定した変形領域に収まります。
void magnet(offset)
オフセット:
move (CS)
move()は、選択されたポイントを指定した値でオフセット
ベクトルまたは数値;すべての軸に適用されるオフセット値
void magnet(xオフセット, yオフセット, zオフセット)
します。オフセットは、選択されたポイントの中心からの相
xオフセット:
対距離で、原点からの距離ではないことに注意してください。
yオフセット: 数値; Y軸方向のオフセット
zオフセット: 数値; Z軸方向のオフセット
void move(オフセット)
オフセット:
ベクトルまたは数値;3本の軸に沿った移動オフセット
rotate (CS)
rotate()は、選択されたポイントを指定された座標軸に沿
void move(xオフセット, yオフセット, zオフセット)
xオフセット:
yオフセット:
数値; X軸方向のオフセット
って指定された度数だけ回転します。
数値; X軸方向のオフセット
数値; Y 軸方向のオフセット
status rotate(度数,軸[,中心点])
zオフセット: 数値; Z軸方向のオフセット
度数:
–28–
数値; 回転する度数
軸:
定数; X 、YまたはZ
中心点:
ベクトルまたは数値; 回転の中心
twist (CS)
status scale(量[,中心点])
rotate()と同様に、 twist()は選択されたポイントを指
量:
ベクトルまたは数値;拡大縮小係数
定された軸を中心として指定された度数だけ回転します。し
中心点:
ベクトルまたは数値; スケールの中心点
かしポイントは、 fixedflex()または autoflex()コマ
ンドで指定したフレックス軸を中心として移動します。
taper (CS)
taper()はscale()に似ていますが、fixedflex()また
status twist(度数,軸[,中心点])
度数:
数値; ひねる度数
はautoflex()が設定したフレックス軸でその有効範囲が定
軸:
定数; X、YまたはZ
義されている点が異なります。
中心点:
ベクトルまたは数値; ひねりの中心
status taper(量[,中心点])
vortex (CS)
量:
ベクトルまたは数値; 先細り係数
中心点:
ベクトルまたは数値;先細りの中心点
vortex()もまた、選択されたポイントを指定された軸を中
心として指定された度数だけ回転します。しかしこのコマン
pole (CS)
ドは、deformregion()コマンドにより指定したパラメー
taper()と同様、 pole()もscale()ファミリーの1つで
すが、これは deformregion()を使ってその有効範囲を制
タを持つ変形領域内で演算を行います。
限した変形領域を使う点が異なります。
status vortex(度数,軸[,中心点])
度数:
数値; ねじる度数
軸:
定数; X、YまたはZ
中心点:
ベクトルまたは数値; ねじりの中心
status pole(量[,中心点])
scale (CS)
量:
ベクトルまたは数値;ポール係数
中心点:
ベクトルまたは数値; ポール中心点
bend (CS)
scale()は、選択されたポイントを与えられた係数を使って
このコマンドは選択されたポイントを、オプションで指定し
拡大縮小します。オプションで中心を指定します。係数を1と
た中心点の回りで一定方向に指定角度だけ曲げるのに使いま
すれば、どの軸方向でもポイントの位置は変わりません。
す。bend()は、 fixedflex() または autoflex() のい
たとえば、オブジェクトをX軸およびY軸方向に1/2縮小して、
Z軸方向には縮小しない場合は、次のようになります。
ずれかにより設定したフレックス軸に固定します。
status bend(角度,方向[,中心点])
量:
数値;ベンドする角度
例
方向:
数値;角度で指定したベンドの方向
scale(<.5,.5,1>);
中心点:
ベクトルまたは数値; ベンドの中心点
この例では、センターベクトルが与えられていないことにご
注意ください。この場合、センターベクトルはデフォルトで
jitter (CS)
原点(つまり<0,0,0>)となり、各軸の値はここからの相対
jitter()は、選択されたポイントを次に挙げる4つの変位
距離となります。
関数で乱数処理します。
–29–
UNIFORM
GAUSSIAN
NORMAL
ポイントは、一定の範囲に分布します。(デフォルト)
makebox (CS)
開始点の周囲にベル曲線のオフセットを適用します。
このコマンドは、指定された大きさと指定された数の面を持
ローカルの面に対する法線の両方向にポイントを移動し
つ3次元のボックスオブジェクトを作ります。
ます。
RADIAL
中心点パラメータにより与えられた中心点を通過する直
status makebox(底辺,上辺[,セグメント数])
線に沿って、ポイントを両方向に移動します。
jitter()関数のプロトタイプは次のようになります。
status jitter(半径[,タイプ[,中心点]])
半径:
数値; ジッター半径
タイプ:
定数; UNIFORM,GAUSSIAN,NORMAL, または
ベクトルまたは数値; 低い方の境界ポイント
ベクトルまたは数値;高い方の境界ポイント
セグメント数:
ベクトルまたは数値;ボックスセグメント数
makeball (CS)
このコマンドは、3次元の地球のような球体を作ります。
RADIAL
中心点:
底辺:
上辺:
status makeball(半径,サイド数,セグメント数[,中心点])
ベクトルまたは数値;RADIAL が使う中心点
半径:
ベクトルまたは数値;球体の半径
サイド数:
整数; 球面サイドの数
smooth (CS)
セグメント数:
整数; スフィアセグメントの数
smooth()は、関連ポイントを使っているポリゴン内の"ねじ
中心点:
ベクトルまたは数値; 球体の中心
れ"を取り去ります。
maketesball (CS)
status smooth(繰り返し数[,強さ])
繰り返し数:
数値; 繰り返す回数
強さ:
数値; スムース処理の強さ
maketesball()を使うと、モザイク状の球体を作ることが
できます。モザイク状の球体とは、4角形ポリゴンを1 2角形
にしたものです。レベルパラメータが、適用するモザイク処
理の量を決定します。
quantize (CS)
このコマンドを使うと、サイズパラメータにより定義された3
status maketesball(半径,レベル[,中心点])
次元グリッドの中に、選択ポイントをすべて配置することが
半径:
ベクトルまたは数値; 球体の半径
できます。
レベル:
整数; モザイク化のレベル
中心点:
ベクトルまたは数値; 球体の中心
status quantize(サイズ)
サイズ:
ベクトルまたは数値;3 次元グリッドを定義します
makedisc, makecone (CS)
makedisc()コマンドを使用すると、指定した数の側面とセ
mergepoints (CS)
グメントを持つ円柱状オブジェクトを作ることができます。
mergepoints()を使うと、特定の最短距離内にある選択さ
側面の数が多ければそれだけなめらかな円柱になります。
れたポイントを結合できます。オプションの距離値を省略し
makecone()は、makedisc()と同じパラメータを受け取
ります。しかしmakecone()は、円柱ではなく、円錐を作成
た場合は、それは自動的に計算されます。
status mergepoints([距離])
距離:
します。
数値;ポイント間の最短距離
–30–
status makedisc(半径,上面,底面,軸,側面数,セグメント数
[,中心点])
maketext(文字,インデックス[,コーナータイプ[,字間[,スケー
ル[,軸[,位置]]]]])
半径:
ベクトルまたは数値; 底面円の半径
返す値:
数値;でき上がるモデラーオブジェクトの幅(単位m)
上面:
数値; 軸上の円筒の頭
文字:
文字列; 変換するテキスト
整数; fontload()が返すフォントインデックス
底面:
数値; 軸上の円柱の底面
インデックス:
軸:
定数; X、YまたはZ
コーナータイプ: 定数; SHARPまたはBUFFERED
側面数:
整数; 側面の数
字間:
数値; 文字の間隔
セグメント数:
整数; セグメントの数
スケール:
数値; 文字のスケーリング係数
中心点:
ベクトルまたは数値; オブジェクトの中心
軸:
定数; X、YまたはZ
位置:
ベクトルまたは数値;文字の最初の位置
maketext (CS)
この関数は、文字列の形をしたモデラーオブジェクトを作り
lathe (CS)
ます。できあがるオブジェクトは、fontload()関数でロー
lathe()は、カレントオブジェクトを指定された軸の回りで
ドされた文字フォントの形となります。fontload()により
自転させ、指定された数の側面を持つ新しいオブジェクトを
返されるフォントインデックス値が、 maketext()関数に渡
作ります。
されなければなりません。
Lathe(回転体)処理されるオブジェクトは、通常は2次元テ
次の短いLScriptコードは、これらの関数(logo.lsスクリプト
ンプレートです。
例に入っています)の使い方の実例です。
status lathe(軸,側面数[,中心点[,終了角[,開始角]]])
例
軸:
定数; X, Y, Z
findex = fontload(fontName);
側面数:
整数; 新しいオブジェクトの数
if(findex != nil)
中心点:
ベクトルまたは数値; 回転体処理をする際の中心
終了角:
数値; 度数であらわした終了角
開始角:
数値; 度数であらわした開始角
{
maketext("LScript",findex);
maketext()は、できあがるモデラーオブジェクトの幅(単
extrude (CS)
位はメートル)を返します。
extrude()を使うと、オブジェクトを指定された軸方向に
延ばせます。オプションでセグメントの追加もできます。
status extrude(軸,距離[,セグメント数])
軸:
定数; X 、YまたはZ
距離:
数値; 軸方向に延ばす距離
セグメント数:
整数; セグメントの数(デフォルトは1)
mirror (CS)
このコマンドは、指定されたデータを1 8 0゜回転しての面対
称体を作ります。
–31–
status mirror(軸,オフセット)
status pathextrude(ファイル名[,ステップ[,開始値[,終了
軸:
定数; X 、YまたはZ
値]]])
オフセット:
数値; 軸と平面とのオフセット
pathclone, pathextrude (CS)
これら2つのコマンドを使うと複製たり、LightWave3D Layoutで作成してセーブしたモーションパス方向にオブジェクト
ファイル名:
文字列; モーションパス・ファイルの名称
ステップ:
数値; 作成するオブジェクト/ セグメントの数
開始値:
数値; 開始カウント
終了値:
数値; 終了カウント
railclone、railextrude (CS)
を延ばすことができます。オプションで開始、終了およびス
railclone()および railextrude()は、オブジェクト
の複製をしたり延ばすという点で p a t h c l o n e ( ) および
テップパラメータをループの計数の引数とすることができま
す。これらを省略した場合は、モーションパスファイルに埋
pathextrude()によく似ています。しかしrailコマンドは、
め込まれている開始および終了フレームを開始および終了と
モーションパスファイルではなくモデラー曲線を使って演算
して使用し、ステップ値はデフォルトで1となります。これら
します。いずれのコマンドが使う曲線(Rail)も、そのときア
の値を指定すると、モーションパスファイル内の値を書き換
クティブなバックグラウンドレイヤーになければなりません。
えることができます。
status railextrude(セグメント,分割,フラグ[,強さ])
開始および終了値を変えれば、オブジェクトをこれらの値で
表されるモーションパス部にのみ従って複製処理をしたり延
セグメント:
数値; セグメントカウント(0=compute)
ばすことができます。たとえば、横断するのに3 3 0フレーム
分割:
定数; KNOTSまたはLENGTHS
フラグ:
文字列; 方向
強さ:
数値; スケールされる量
必要なモーションパスをロードして、次のようなコマンドを
発行すると、
例
axisdrill (CS)
pathextrude("my.mot",1,200,300);
axisdrill()は、アクティブなバックグラウンドレイヤー
内の2次元オブジェクトをテンプレートとして使って、アクテ
オブジェクトは、モーションパスのフレーム2 0 0の位置から
ィブなフォアグラウンドレイヤー内にそのオブジェクトの形
延びはじめ、フレーム3 0 0の位置まで続けられます。フレー
の"穴を開け"ます。 axisdrill()には、次のようなドリル
ム1から199までと、フレーム301から330までの範囲でオブ
処理が可能です。
ジェクトが延びる部分のパスは空になります。
CORE
pathclone()を使ってオブジェクトを複製すると、各ステ
フォアグラウンドのポリゴンにバックグラウンドのテン
プレートの形に合う穴を開け、その内側を残します。
ップごとに一意なオブジェクトを作ることができます。
TUNNEL
pathextrude()を使ってオブジェクトを延ばすと、各ステ
COREとは反対に、テンプレートの形に合う部分のポリ
ゴンを取り除き、外側部分を残します。
ップごとに新しいセグメントをつけ加えて新しいオブジェク
SLICE
トが1つできます。
テンプレートのエッジに沿って切り開き、フォアグラウ
ンドオブジェクトに穴を開けます。
STENCIL
どちらのコマンドも、カウントおよびタイプというパラメー
SLICEと同じですが、テンプレートの形に収まるすべて
のポリゴンにサーフェイスの名称を割り当てられます。
タを受け取ります。
–32–
ステンシル処理を指定する際は、オプションでサーフェイ
bevel (CS)
ス・パラメータを使います。
bevel()コマンドを使うと、インセットおよびシフト量を指
定してオブジェクトにベベルエッジを追加できます。
status axisdrill(操作,軸[,サーフェイス])
操作:
定数; CORE,TUNNEL,SLICE またはSTENCIL
status bevel(インセット,シフト)
軸:
定数; X, YまたはZ
インセット:
数値;ポリゴン平面方向に対する一様な変位量
サーフェイス:
文字列; (STENCILの場合)サーフェイスの名称
シフト:
数値;ポリゴン平面に垂直方向の変位量
soliddrill (CS)
shapebevel (CS)
soliddrill()は、ほとんど axisdrill()と同じですが、
shapebevel()もまた、オブジェクトに面取りエッジを追
次の点が違います。a)これはアクティブなバックグラウンド
加するものです。しかしこれは、文字列中のインセット/シフ
レイヤー内の3次元オブジェクトを使います。b)この場合は、
ト値を何組も受け取ることができます。文字列内には、イン
2つのオブジェクトのボリューム(フォアグラウンドおよびバ
セット/シフト値を空白で区切って入れます。 bevel()関数
ックグラウンド)が重っていなければなりません。
をいくつか反復しても同じ効果が得られますが、その結果は
つねに正しいわけではありません。自己反復効果が起こるた
status soliddrill(操作[,サーフェイス])
操作:
定数; CORE,TUNNEL,SLICEまたはSTENCIL
サーフェイス:
文字列; (STENCILの場合)サーフェイスの名称
めです。
スクリプト例r o u t e r . l sでは、このコマンドを多用してこの効
果を出しています。このコマンドの短いコード例を、このス
クリプト例から引用します。
boolean (CS)
このコマンドは、アクティブなフォアグラウンドレイヤーの
例
オブジェクトと、アクティブなバックグラウンドレイヤーの
s = string(-wide," ",wide," ",-wide," ",deep
オブジェクトを結合します。次の4種類のブーリアン処理をサ
/ 2);
ポートしています。
UNION
shapebevel(s);
各オブジェクトボリュームを1つの新しいオブジェクトに
まとめます。2つのオブジェクトが重なる部分の内部サー
フェイスは削除されます。
SUBTRACT
status shapebevel(パターン)
バックグラウンドオブジェクトのボリュームをフォアグ
パターン:
ラウンドオブジェクトから取り去ります。
INTERSECT
ADD
文字列;inset/shiftの対
2つのオブジェクトの共通領域からオブジェクトを作りま
す。
smoothshift (CS)
バックグラウンドオブジェクトをフォアグラウンドオブ
このコマンドは、選択したポリゴンを指定したオフセットだ
ジェクトに加算します。ポリゴンが交わるところには共
け移動します。最大角度以上の角度を指定すると、サーフェ
通のエッジが作られます。
イスが壊れます。
status boolean(操作)
操作:
このコマンドのプロトタイプは次のようになります。
status smoothshift(オフセット[,最大角度])
定数; UNION,SUBTRACT,INTERSECTまたは
ADD
–33–
オフセット:
数値; 移動のオフセット
最大角度:
数値; 度数で表した最大角度
flip (CS)
status removepols(void)
flip()を使うと、選択したポリゴンのサーフェイスノーマ
ルを裏返します。これを使って、モデラー曲線の方向を逆に
unifypols (CS)
することもできます。
unifypols()は、重なりあうポリゴンを結合します。
status flip(void)
status unifypols(void)
triple (CS)
subdivide (CS)
triple()を使うと、アクティブなフォアグラウンドレイヤ
subdivide()を使うと、すべての三角形を小さな三角形4
ーにあるポリゴンすべてを三角形に変換します。
つに分割します。このコマンドはまた、四辺形をさらに小さ
な四辺形に分割できます。 subdivide()には、3つの形式
status triple(void)
があります。
特に、オブジェクトを分割する前(特に4つの側面を持つポリ
FLAT
ゴンの場合)、t r i p l e ( )するとよいでしょう。次の短いコ
ポリゴンを分割して、新規のポリゴンを元のものと同じ
平面上に置きます。
ード例はその好例です。
SMOOTH
分割されたポリゴンがもとのものと同じ曲率を保持する
ようにします。
例
METAFORM
points = polycount();
なめらかさの度合を最大レベルにします。より細かなも
のほどより細かくスムース処理をします。
if(points[5] or points[6])
status subdivide(モード,最大角[,最大角])
//4つ以上の側面を持つポリゴンがあります
triple()
モード:
定数; FLAT, SMOOTHまたはMETAFORM
最大角:
数値; 度数で表した最大角
subdivide(METAFORM);
fracsubdivide (CS)
freezecurves (CS)
fracsubdivide()はsubdivide()に似ていますが、位
freezecurves()を使用すると、選択したモデラー曲線を
置関数としてフラクタル変位値を新規の頂点それぞれに適用
ポリゴンに変換できます。
します。
status freezecurves(void)
status fracsubdivide(モード,フラクタル[,最大角])
モード:
定数; FLAT, SMOOTHまたはMETAFORM
alignpols (CS)
フラクタル:
数値; フラクタル変位量
このコマンドは、選択したポリゴンすべてを"反転して"(でき
最大角:
数値; 度数で表した最大角
る限り)同方向に向くようにします。
selpoint (CS)
status alignpols(void)
全LScriptコマンド中、パラメータ構造がもっとも複雑なもの
のひとつです。 s e l p o i n t ( ) には2つの メジャーモード
removepols (CS)
r e m o v e p o l s ( ) は、選択したポリゴンすべてを削除して、
(S E TとC L E A R )と、多くのマイナーモードがあります。そ
そのポイントのみを残します。
–34–
れぞれには、独自のパラメータカウントとパラメータタイプ
があります。selpoint()のメジャーモードは次のような動
status selpoint(メジャーモード[,マイナーモード,パラメー
作をします。
タ])
もしマイナーモードが次に存在しこれを SETすると、選択す
メジャーモード:
定数; SETまたはCLEAR
るべきポイントを定義できます。またマイナーモードが次に
マイナーモード:
定数; VOLUME, CONNECT,NPEQ,NPLT
またはNPGT
存在しこれを CLEARすると、選択を解除するポイントを定義
パラメータ:
できます。これらの2つのメジャーモードのいずれかが、かな
値; 前述のマイナーモードパラメータ
らずselpoint()の最初のパラメータとなります。この2つ
はかならず付けなければならないパラメータですが、パラメ
selpolygon (CS)
ータリストにこれだけを指定することも可能です。(つまり、
selpolygon()は、selpoint()と同種のコマンドで、こ
selpoint(CLEAR)とすれば、そのとき選択されている
れを使うとスクリプトのプログラマは、単一ポイントではな
くポリゴン全体を選択/選択解除できます。このメジャーモー
ポイントすべての選択を解除します)
。
ドはselpoint()と同じですが、マイナーモードの数や機能
selpoint()がサポートするマイナーモードを使うと、スク
は異なります。
リプトのプログラマはポイントをさまざなまな方法で選択で
マイナーモード 引数
きます。
VOLEXCL
selpoint()のマイナーモードを次にまとめます。
を示す2つのベクトル。
マイナーモード
引数
VOLUME
バウンディングボックスのローポイントとハイポイン
VOLINCL
トを示す2 つのベクトル。
CONNECT
なし
NPEQ
ポリゴンが含むべきポイント数を示す数字。
CONNECT
NVEQ
NVLT
なし
ポリゴンが持つべき頂点数を示す数字。
ポリゴン内が持つべき頂点数の最高値から1 を引いた数
字。
ポリゴン内にあるべきポイント数の最高値から1 を引
SURFACE
ポリゴンが持つべき頂点数の最低値に1を加えた数字。
ポリゴンに割り当てられているサーフェイスの名称を示
す文字列。
いた数字。
NPGT
バウンディングボックスのローポイントとハイポイント
を示す2つのベクトル。
NVGT
NPLT
バウンディングボックスのローポイントとハイポイント
ポリゴン内にあるべきポイント数の最低値に1を加え
た数字。
スクリプトは、かならず selmode() コマンドを使っ
てU S E Rモードにしなければなりません。そうしない
と、selpoint()(およびselpolygon())は正しく動作
しません。
次に、selpoint()のプロトタイプを示します。
–35–
FACE
CURVE
NONPLANAR
なし
なし
平面の選択限界を示すオプションの数値。
setsurface (CS)
setsurface()は、新規のデータが割り当てられるサーフ
selpoint()の場合と同様 selpolygon() を正し
ェイスの名称を設定します。もしこれが存在しなければ、新
く 動 作 さ せ る に は 、 ス ク リ プ ト セ ッ シ ョ ンは
規に作られます。
s e l m o d e ( )コマンドを使ってかならずUSERモードにして
おかなければなりません。
status setsurface(名称)
名称:
status selpolygon(メジャーモード[,マイナーモード,パラメ
ータ])
メジャーモード:
定数;SETまたはCLEAR
マイナーモード:
定数; VOLEXCL,VOLINCL,CONNECT,
getdefaultsurface (IN)
このコマンドは、そのとき選択されているサーフェイスの名
称を返します。
NVEQ,NVLT,NVGT,SURFACE,FACE,
パラメータ:
文字列; 新規のサーフェイスの名称
CURVEまたはNONPLANAR
varies; 前述のマイナーモードパラメータ
getdefaultsurface(void)
返す値:
文字列; サーフェイス名
selinvert (CS)
changesurface (CS)
このコマンドは、そのときの選択状態を逆にします(つまり
changesurface()は、そのとき選択されているポリゴン
選択されアイテムは選択解除となり、非選択アイテムが選択
すべてを、新規のまたは既存のサーフェイス名称に割り当て
されます)
。
ます。
status selinvert(void)
status changesurface(名称)
名称:
selhide (CS)
文字列;選択されたポリゴンが所属することになるサ
ーフェイスの名称
selhide()は、選択されているデータか選択されていない
データかのどちらかを見えなくします。 SELECTEDオプショ
ンを使うと選択されているデータを隠し、UNSELECTEDオプ
nextsurface (IN)
ションを使うと選択されていないデータを隠します。
内 部 リ ス ト を 閲 覧 で き ま す。パラメータを付けずに
nextsurface()を使うと、モデラーのサーフェイス名称の
status selhide(選択)
nextsurface()を呼び出すと、モデラーのリスト内の最初
選択:
のサーフェイス名称を返します。nextsurface()にサーフ
定数;SELECTEDまたは UNSELECTED
ェイスの名称を渡すと、その次のサーフェイス名称を返すこ
selunhide (CS)
とができます。与えられたサーフェイス名称がリストの最後
このコマンドは selhide()と同種のもので、隠されたデー
のエントリの場合は、値nilを返します。
タを見えるようにするものです。
status selunhide(void)
–36–
例
copysurface (IN/1.2)
// 現在のサーフェイス名称すべてを表示する
このコマンドはモデラー内部のサーフェイスリストに新しい
サーフェイス名を加え、既存の任意のサーフェイスの属性を
新しいサーフェイスにコピーします。
var surface = nextsurface();
info(surface);
status copysurface(オリジナル,新規)
while(true)
オリジナル:
文字列; 既に存在しているサーフェイス名
{
新規:
文字列; 新しいサーフェイス名
if((surface = nextsurface(surface)) ==
nil)
fontcount (IN)
break;
fontcount()は、そのときモデラーにロードされているフ
info(surface);
ォント数を返します。内部フォントリストが空の場合は、
nilを返します。
}
fontcount(void)
プロトタイプは次のようになります。
返す値:
整数; ロードされているフォント数
nextsurface([名称])
返す値:
文字列; サーフェイスの名称
fontindex (IN)
名称:
文字列; オプションサーフェイス名称
fontindex()にフォントの名称を与えると、そのフォント
のインデックス値を返します。指定したフォントが見つから
renamesurface (IN)
ない場合は、nilを返します。
renamesurface()を使うと、スクリプトのプログラマは
既存のサーフェイス名称を変更できます。名前を変更すると、
もとのサーフェイス名称は失われます。
fontindex(名称)
整数; フォントインデックス値
返す値:
名称:
文字列; フォント名称
status renamesurface(オリジナル,新規)
オリジナル:
文字列; 既存のサーフェイス名称
fontname (IN)
新規:
文字列; 新規のサーフェイス名称
fontload()または fontindex()が返したフォントイン
デックスを与えられると、fontname()は指定されたフォン
createsurface (IN)
ト名称を返します。与えられたインデックスが有効ではない
このコマンドは、新規のサーフェイス名称をモデラーの内部
ときは、nilを返します。
リストに追加します。その名称を持つサーフェイスがすでに
fontname(インデックス)
存在する場合は、なにも起こりません。
status createsurface(名称)
名称:
文字列; 新規のサーフェイス名称
–37–
返す値:
文字列またはnil; フォント名称
インデックス:
整数; フォントインデックス値
fontload (IN)
他のプラグインを呼び出すときに使う名称は、プラグインメ
fontload()を使うと、スクリプトのプログラマはポストス
ニューボタン に現れるものと同じでなければなりません。プ
クリプトフォントをモデラーにロードして、テキスト作成コ
ラグインに渡す引数は、そのプラグインがどのようにプログ
マンドで使うことができます。特定のフォントでの作業を終
ラムされているかに依存します。プラグインはほとんどの場
えたら、これと同類のコマンド fontclear()(後述)を呼
合、パラメータを受け取りません。仕様として、そのように
び出さなければなりません。
は設計されていないのです。
例
status cmdseq(名称[,引数])
var fontName = getfile("Select a Font");
名称:
文字列; プラグイン名称
引数:
文字列; プラグインにより値は変化します
if(fontName == nil)
return;
swaplayers (CS)
var findex = fontload(fontName);
swaplayers()を使うと、そのとき選択されているレイヤ
if(findex != nil)
ーを逆にできます。フォアグラウンドレイヤーが選択されて
{
いればバックグラウンドレイヤーを選択することになり、選
maketext("LScript",findex);
択されているバックグラウンドレイヤーは、アクティブなフ
fontclear(findex); // 直ちにフォントを解放
ォアグラウンドレイヤーになります。
・・・
このコマンドは、モデラー内でレイヤー切り替えに使う一重
引用符(')をタイプした場合と同じです。
プロトタイプは次のようになります。
void swaplayers(void)
fontload(名称)
返す値:
整数; フォントインデックスまたはnil
名称:
文字列; オプションでパスを付けたフォントの名称
getfile (CS)
getfile()を使うと、LScriptにファイル選択用インターフ
fontclear (IN)
ェイスを提供できます。ユーザーにファイルを指定してもら
fontload()コマンドを使ってロードしたモデラーフォント
が必要なくなったら、fontclear()を呼び出します。
う必要がある場合、 getfile()がファイル選択ダイアログ
status fontclear(インデックス)
インデックス:
ボックスを表示して、ユーザーが選択したファイルの名称
(パス情報も)を返します。ユーザーがキャンセルすれば、
getfile()はnilを返します。
整数; フォントインデックス値
getfile()のパラメータすべては省略可能です。ダイアロ
グボックスのタイトル、ファイル名称マスク、デフォルトデ
cmdseq (CS)
ィレクトリも指定できます。
cmdseq()を使うと、モデラーにインストールされている他
のプラグインを LScriptで呼び出せます。このプラグインへの
インターフェイスは単一方向性です。つまり、情報を渡すこ
とはできますが、戻り値は返せません。
–38–
getfile([タイトル[,マスク[,ディレクトリ]]])
getempty(void)
タイトル:
返す値:
文字列またはnil; ファイルの名称、ダイアログ
整数[]; 1つ以上のレイヤー値
ボックスタイトル
マスク:
文字列;使用するファイルマスク( ワイルドカードも
getemptyfg(void)
使用可能)
ディレクトリ:
返す値:
文字列; 開始のディレクトリパス
整数[]; 1つ以上のレイヤー値
getemptybg(void)
fglayers, bglayers (IN)
返す値:
fglayers()コマンドは、フォアグラウンドでそのとき選択
されているモデラーレイヤーを返します。
整数[]; 1つ以上のレイヤー値
getemptyfg()および getemptybg()は、それぞれその
またbglayers()コマンドを呼び出せば、バックグラウンド
とき選択されているフォアグラウンドレイヤーとバックグラ
レイヤーが返ります。1から1 0までの範囲のレイヤー番号が
ウンドレイヤー内の空レイヤーを返します。
返されます。これらのコマンドからの戻り値を配列に割り当
てることがひんぱんにありますが、非配列変数にも割り当て
moninit (IN)
ることができます。その場合は、最初の戻り値のみが保存さ
このコマンドは、モニター制御コマンドに対するエントリー
れます。
ポイントです。 moninit()は、スクリプトのモニターウイ
普通、LScriptがセッティングを変更する前にこれらのコマン
ンドウを初期化します。このコマンドは、他のモニターコマ
ドを使って、ユーザーがアクティブに選択したレイヤーを覚
ンドが使われる前に呼び出します。
えます。変更後は、これらの値をsetlayer()(または配列
モニターシステムというものは、基本的には進行インジケー
にアクティブなバックグラウンド情報があれば
ターです。進行インジケーターにより、ユーザーは進行状況
を知ったり、コンピュータが停止していないことなどを確認
setblayer()に)渡して、ユーザーのもとのレイヤーセッ
できます。作業を完了するまでいくつのステップが必要かを
ティングを復元します。
伝えて、モニターを初期化します。モニターシステムはこの
getempty, getemptyfg, getemptybg (IN)
値を利用して、グラフィカルなプログレスバーを表示します。
これらのコマンドは、オブジェクトデータを含まないレイヤ
これを見ると、ユーザーは完了までの残り時間がわかるので
ーを返します。
す。
getempty()の場合、アクティブか非アクティブかに関わら
オプションで、モニターダイアログボックスの表示中にユー
ず、空のレイヤーすべてが返されます。
ザーに見せたいメッセージを与えることができます。モニタ
ーウインドウは、実際にはダイアログボックスだという点に
ご注意ください。ユーザーは、ダイアログボックスのキャン
セルボタンをいつでも押すことができます。このアクション
はmonstep()関数(後述)が処理します。
–39–
デラーの他の部分が使えるようにします(モニターウインド
void moninit(ステップ[,メッセージ])
ステップ:
整数; 完了までのステップ数
メッセージ:
文字列; ユーザーに表示したいメッセージ
ウをアクティブにできるのは1度に1つのみです)
。
void monend(void)
monstep (IN)
reqbegin (CS)
monstep()を使うと、進行インジケーターを指定したステ
モデラーにはインターフェイス機構が装備してありますから、
ップだけ進められます。値が与えられていない場合、先に進
ユーザーはプラグインをインタテクティブに操作できます。
めるステップ数はデフォルトの1になります。より大きな値を
LScriptはこの機構を起動して、スクリプトのプログラマが同
指定すれば、さらにプログレス・インジケーターを進めるこ
様の機能を利用できるようにします。reqbegin()は、これ
とができます。
らのインターフェイス関数へのエントリーポイントです。
monstep()は、ブール値を返します。ほとんどの場合、こ
reqbegin()が呼び出されると、モデラーの "リクエスタ"が
の値はfalseです。しかし、ユーザーがモニターウインドウ
初期化されます。リクエスタとは、ユーザーからの情報や選
上のキャンセルボタンを押すと、このコマンドはtrueを返し
択事項を集めるための入力ダイアログボックスのことです。
ます。そうなった場合、スクリプトをできる限りすみやかに
またこれは、情報やメッセージをテキストとして伝えるため
終了する必要があります。
にも使われます。
ブール値; キャンセルボタンが押されたときのみ
r e q b e g i n ( )を呼び出すと、リクエスタモードに入ります。
その他のリクエスタ関連関数(たとえば、 addcontrol())
true
を使うには、このモードがアクティブになっていなければな
整数; オプションの進める数
りません。また、終了するには reqend()を呼び出さなけれ
boolean monstep([ステップ])// 整数; オプションの進める
返す値:
ステップ数:
ばなりませんが、リクエスタモード中の任意のときにスクリ
例
プトを終了できます。もし r e q e n d ( ) の発行を忘れても
editbegin();
LScriptがこれを自動的に発行します。
・・・
reqbegin()は、リクエスタダイアログで使うタイトル用に
if(monstep())
1つの引数を受け取ります。
{
void reqbegin(タイトル)
setlayer(fg);
タイトル:
setblayer(bg);
editend(ABORT);
文字列; ダイアログボックスタイトル
reqend (CS)
return;
reqend()は、リクエスタモードを終了する関数です。ユー
}
ザー入力のすべての処理が完了した後、リクエスタダイアロ
グを閉じるにはかならずこれを使います。
monend (IN)
このコマンドは、開いているプログレスウインドウを閉じて、
モニターシステムを完了してモニターシステムを解放し、モ
–40–
void reqend(void)
reqpost (CS)
例
このコマンドは、必要なフィールドを設定してリクエスタダ
・・・
イアログの構築が完了したこと、そしてユーザーとの対話の
name = "BillyBob";
ためにダイアログを表示したいことをリクエスタシステムに
age = 18;
通知します。
c1 = ctlstring("Your name?",name);
reqpost()は、与えられた値を使ってユーザーが処理を継
続したいのかそうではないのかを示すブール値( trueまたは
c2 = ctlinteger("Your age?",age);
・・・
false)を返します。値 trueは、ユーザーがOKを選択した
こと、つまり処理を始めることを示します。また false値が
cltvector()はパラメータとして比較的柔軟なフォーマット
返れば、ユーザーは C a n c e lを選択したことになりますから、
を受け取ることができます。単一のベクトルデータタイプ、3
スクリプトを終了します。
つのフィールドを埋める単一の数値、あるいはそれぞれの編集
フィールドを初期化するために3つの別々の値をあてはめるこ
reqpost(void)
返す値:
とができます。
boolean; ユーザーが"OK"を選択すればtrue
ctldistance
ctldistance()関数は ctlnumber()と同様に使用する
ctlstring, ctlinteger, ctlnumber, ctlvector, ctldistance,
ことができます。しかし、得られた編集コントロールは、モ
ctlchoice, ctltext, ctlcolor, ctlsurface, ctlfont (CS/1.2)
デラーの現在のデフォルトの測定単位に基づいて表示・編集
これらの関数はモデラーLscriptで使われる一連のコントロー
されます。
ルの生成を構成します。それぞれの関数はコントロールタイ
例
トルの最初のパラメータを受け取り、コントロール識別子を
・・・
返し、後でにgetvalue()関数で使用します。
length = .25;
コントロールは2番目のパラメータによって初期値が決められ
c1 = ctldistance("Length",length);
ます。
// デフォルト編集単位がキロメートルとなっている場合
// このフィールドの値は(.25 * 1000) = 250 メートルと
// なります
また、 c t l s t r i n g , c t l i n t e g e r , c t l n u m b e r ,
ctlvectorについては単純なデータタイプ、すなわち文字
列、整数、浮動小数点値、そして浮動小数点値によって構成
・・・
されるベクトルを編集するコントロールを生成するために提
供されています。
ctlchoice
ctlchoice()は3つのパラメータを必要とし、オプション
として4つめのパラメータをとることができます。第1のパラ
メータは他のすべてのコントロール生成関数と同様にコント
ロールのタイトルです。第2のパラメータは整数値で、パネル
が表示された時にあらかじめ選択されている初期値としてプ
ッシュボタンを特定するために使われます。
–41–
第3のパラメータはボタンラベルとして使われる文字列を含む
他のコントロール関数と同様に、 ctltext()は静的テキス
配列参照か、あるいは同じデータを格納する関数コールへ直
トコントロールのコントロールハンドルを返します。しかし、
接置かれる初期ブロックです。選択番号は1から始まります。
コントロールは変化しないので、このハンドルは小さな値と
なります。ダイアログボックスを再表示する前にテキストを
例
変更しない場合にはsetvalue()を使うこともできます。
booleans[1] = "Yes";
booleans[2] = "No";
ctlcolor
choice = 2; // "No"を初期値に設定する
c1 = ctlchoice("Use random
このコントロールは ctlvector() と似ており、3つの別々
height?",choice,booleans);
c t l v e c t o r ( ) が浮動小数点の編集ができるのに対し、
ctlcolor()によるフィールドには整数値しか入力すること
の数値編集フィールドを持つコントロールを表示しますが、
オプションの4番目のパラメータは選択リストの配置を指定す
ができません。
るために使われ、選択リストを垂直あるいは水平にすること
ctlvector()と同様に、 ctlcolor()はパラメータタイ
ができます。省略した場合は水平方向がデフォルトとして使
用されます。
プを組み合わせることも可能です。単一のベクトル型データ
(3つのフィールドを全て整数値で埋める)あるいは、それぞ
例
れの編集フィールドで初期化するために3つの独立した整数値
choice = 1;
を扱うことも可能です。
// "No" を初期値に設定し 垂直の選択リストを作成する
c1 =
ctlsurface, ctlfont
ctlchoice("Quadrant?",choice,@"90","180","270
これら2つの関数はモデラーのサーフェイスとフォントの属性
"@,true);
をそれぞれ管理することができます。生成されたコントロー
ルは他のコントロールも多数保持しており、コントロール型
ctltext
の特別な機能に関連づけられます。
ctltext()はリクエスタダイアログボックスに静的なテキ
どちらの関数も第1のパラメータがコントロールタイトルとな
ストを加えるために使われます。この静的テキストはユーザ
ります。ctlsurface()は2番目の文字列パラメータがサー
に対して特に指示をしたいときなどに使われます。また、
フェイスコントロールを初期化するためのサーフェイス名だ
ctltext()は文字列型の変数を取り扱うこともでき、他の
と認識します。ctlfont()の2番目のパラメータは整数値で、
すでにロードされているフォントのインデックスを示します。
コントロール生成関数と同様に最初の文字列は常にコントロ
ールタイプとして扱われます。
LScript旧バージョンにあった、 addcontrolおよび,
addtext関数は、削除されました。
例
ctltext("WARNING",
getvalue (CS)
//最初の要素はタイトル
"This operation could take a long
getvalue()を使うと、入力フィールド内の値を取得できま
す。addcontrol() が返したコントロールハンドルを、こ
time,","and create very many points if
の関数に与えなければなりません。戻り値のタイプは、入力
Level is high");
フィールドのタイプに依存します。通常では、 a d d c o n–42–
t r o l ( ) で入力フィールドを作るのに使ったもとの変数に
getvalue()の戻り値を割り当てます。
listadd()を使うと、ユーザーコマンドメニューに表示す
る名称を設定できます。また、選択事項の処理に使うサーバ
ー(LScriptsの場合サーバの名称は"LScript")や、そのエント
getvalue(ハンドル)
返す値:
あらゆる型; フィールド内のデータ値
ハンドル:
整数; コントロールハンドル
リーを表すファイルの名称(オプションでパスも)を設定で
きます。
listremove()を使うと、エントリーをユーザーコマンド
setvalue (CS)
メニューから削除できます。メニューエントリーの名前を指
reqend()が呼び出されるまで、構築されたリクエスタダイ
定するだけでかまいません。
アログは必要に応じて何回でも入力のためにユーザーに表示
サーバーベースのエントリーがこのようにユーザーコマンド
できますが、コントロール自体は修正できません。修正する
メニューに入ると、モデラーはそれを内部コマンド(たとえ
には、まずカレントリクエスタを reqend()で消してもう一
ばプラグイン追加)およびプラグインとは別に保持します。
度 r e q b e g i n ( ) で新しいものを作りなおし、 a d d c o n-
そうするは、サーバーベースのエントリーを特定のファイル
trol()で新規のコントロールを付ける必要があります。し
に格納します。モデラーを起動するたびにこのファイルが自
かし、コントロール内の値は変更してから再表示することが
動的にリロードされます。しかし、モデラーがこれらのコマ
できます。
ンドを認識するためには、それを追加したセッションを終了
setvalue()を使うと、既存のリクエスタコントロールの値
する前にそれを保存しておく必要があります。後でロードす
を修正できます。これは、修正するコントロールに対するハ
るために新規エントリーを保存するには、設定メニュー内の
ンドルと、新しい値として使う変数または定数値を受け取り
コマンド編集コマンドを使います。詳細は、ご使用のモデラ
ます。この実例については、ディスクに入っているlightswa.ls
ーマニュアルをご覧ください。
スクリプトをごらんください。
status listadd(タイトル,サーバー,ファイル)
void setvalue(ハンドル,値
ハンドル:
値:
整数; コントロールハンドル
タイトル:
文字列; Userメニュー内のエントリーのタイトル
サーバー:
文字列; エントリーの処理に使われるサーバの名称
ファイル:
データタイプ; 入力フィールドに対する新しい値
文字列; このエントリーがポイントするディスクフ
ァイル
status listremove(タイトル)
listadd, listremove (CS)
タイトル:
文字列; 削除するエントリーのタイトル
この2つのコマンドを使うと、LScriptsでモデラーのオブジェ
クトパネルにあるユーザーコマンドメニューにアイテムを追
selmode (IN)
加したり削除することができます。一般的にはこれらのコマ
セレクションモードは、特に s e l p o i n t ( ) および
selpolygon()コマンドといったさまざまなモデラー固有
コマンドが利用します。セレクションモードは、 GLOBALま
たはUSERのいずれかのモードになります。デフォルトのモー
ドはGLOBALセレクションです。
ンドを使って、LScriptsを直接追加するユーザーコマンドメニ
ューに追加します。スクリプトをこうして追加しておけば、
LScriptを呼び出してからファイル選択ダイアログボックスで
スクリプトを選択する必要はなく、LScriptsを直接実行できま
す。
–43–
GLOBALセレクションモードでは、ユーザーがどのデータ軸
数が宣言してあると、それらは隠れます。 editend() を使
を選択したかにかかわらずアクティブなフォアグラウンドレ
ってメッシュデータエディットモードモードを終了すると、
イヤー内のすべてのポイント/ポリゴン上でモデラー固有のオ
それらはまた見えるようになります。
ペレーションが実行されます。USERセレクションモードでは、
editbegin()は、そのとき選択されているポイント数を返し
モデラー固有コマンドのオペレーションが実行されるのは、
ます。この数はpoint[]自動配列のサイズと同じになります。
ユーザーが明示的に選択したポイントとポリゴンのみになり
editbegin(void)
ます(またはユーザーが何も選択していない場合は、暗黙的
返す値:
にすべてのポイントおよびポリゴン)
。
USERセレクションモードがアクティブでなければ、選択コマ
ンドselpoint()およびselpolygon()は機能しません。
editend (MD)
editend()を使うと、 editbegin()で開始したメッシュ
void selmode(モード)
モード:
整数; 選択されたポイントの数
データエディットモードを終了できます。呼び出されると、
定数; GLOBAL またはUSER
自動配列point[]とpolygon[]は消滅し、コマンドシーケ
ンス( C S )関数およびコマンドがまた利用できるようになりま
editbegin (MD)
す。
editbegin()は、LScriptがサポートするメッシュデータエ
メッシュデータエディットオペレーション中は、モデラーは
ディット関数 へのエントリー・ポイントです。コマンドシー
オブジェクトデータに加えられたすべての修正をキュー行列
ケンス( C S )コマンドは、ポイントおよびポリゴン集合に対し
に入れます。 editend()コマンドを発行するまでは、修正
てオペレーションを実行できるのに対して、メッシュデータ
はオブジェクトには適用されません。パラメータを e d i-
エディット(MD)オペレーションは、スクリプトのプログラマ
tend()に与えない場合、デフォルトでは修正はオブジェク
トに適用され処理が継続します。しかし editend()にパラ
に個々のポイントやポリゴンデータを直接編集できるように
します。
メータを与えて蓄積した修正事項を破棄してから、オブジェ
editbegin()で、LScriptをメッシュデータエディットモー
クトをそのままにしておくことも可能です。このパラメータ
ドにします。このモードに入ると、ある不思議なことが起こ
は、すべての修正事項を破棄したいことを示すABORTという
ります。
定数、またはゼロではない任意の値とすることが可能です。
1.コマンドシーケンス(CS)コマンドおよび関数はこの時点で無
void editend([ステータス])
効となります。 editend()を使ってメッシュデータエディ
ステータス:
ットモードから出るまで、これらのタイプのプロシージャは
定数; ABORT
呼び出せません。
boundingbox (IN)
2 . 新しい自 動 L S c r i p t 配列が利用できるようになります。
boundingbox()は、指定したレイヤー内のオブジェクトの
point[]という第1の配列には、そのとき選択されているオ
バウンディングボックスを表す上方向および下方向のベクト
ブジェクトポイントすべてのポイントI Dが入ります。第2の
ルを返します。レイヤーが指定されていない場合は、そのと
polygon[]という配列には、そのとき選択されているオブ
き選択されているフォアグラウンドレイヤーがデフォルトと
ジェクトポリゴンすべてのポリゴンIDが入ります。
して使われます。
自動配列point[]とpolygon[]の場合、メッシュデータエ
ディットモードモードのスコープ内で同一名の配列または変
–44–
モードには関係なく、boundingbox() は任意のときに呼び
このデータを使うと、オブジェクトの状態を調べられます。
出せます。しかしboundingbox()がメッシュデータエディ
たとえばオブジェクトを METAFORMする前に、4頂点以上の
ットモードで使われた場合は、レイヤーを指定できませんし
のポリゴンすべてを三角形に変換しておく場合は、次のよう
指定しても無視されます。
な短いコードを使います。
ポイント/ポリゴンデータが指定されたレイヤー内になければ、
例
各ベクトルにはnilが返されます。
var totalpoints[6];
boundingbox([レイヤー])
totalpoints = polycount();
返す値:
if(totalpoints[5] || totalpoints[6])
ベクトル[2]; バウンディングボックスの下方向お
よび上方向のベクトル/データが存在しなければ、
triple();
nil[2]
レイヤー:
subdivide(METAFORM);
整数または整数[]; レイヤー番号の整数配列、また
•••
はカンマで区切ったレイヤー番号
polycount()は任意のときに呼び出せます。メッシュデータ
エディットモード内からのみ呼び出す必要はありません。
pointcount (IN)
pointcount()は、アクティブなフォアグラウンドレイヤ
polycount(void)
ー内でそのとき選択されているポイントの数を返します。こ
返す値:
の値は、editbegin()関数が返す値と同じです。
pointcount()はいつでも呼び出せます。
addpoint (MD)
addpoint()を使うと、新しいポイントをオブジェクトに追
pointcount(void)
返す値:
整数[6]; さまざまなポイント数のポリゴン
加できます。有効なベクトルを与えると、別の関数に提供で
整数; 選択されたポイントの数
きる有効なポイントIDをaddpoint() が返します。何らかの
polycount (IN)
原因から a d d p o i n t ( ) が新規ポイントの作成に失敗すると、
polycount()の戻り値は、 pointcount()のものよりも
nilが返されます。
複雑です。1つのポリゴンが持っている頂点の数により、戻り
addpoint(位置)
値を分類するからです。polycount() は、次の事項を表す
6つの整数要素を返します。
返す値:
point id; 新しいベクトルの識別子
位置:
整数[3],ベクトルまたは数値; 新規ポイントの位置
[1]
選択されたポリゴンの総数
[2]
[3]
[4]
[5]
[6]
ポイントを1つだけ持っている選択されたポリゴンの総数
addpolygon (MD)
ポイントを2つだけ持っている選択されたポリゴンの総数
addpolygon()を使うと、新しいポリゴンをオブジェクト
ポイントを3つだけ持っている選択されたポリゴンの総数
ポイントを4つだけ持っている選択されたポリゴンの総数
ポイントを4つよりも多く持っている選択されたポリゴン
の総数
データに追加できます。1つ以上のポイントIDをこの関数に与
えて新しいポリゴンを作ることができます。1つ以上のポイン
トIDが提供されると、それらは配列に格納されます。
新しいポリゴンは、オプションでサーフェイス名称に割り当
てられます。サーフェイスパラメータが省略された場合は、
–45–
新規のポリゴンはデフォルトサーフェイス識別子に属します。
指定されたサーフェイス名が存在しない場合は、それが新し
addquad(ポイント)
返す値:
く作成されます。
ポイント:
成功すると、新しいポリゴン識別子が返されます。また、失
ポリゴンID; 新規ポリゴン識別子またはnil
ID[4]または4つの個々のポイントID; 四辺形の
構築に使うポイント
敗した場合はnilが返されます。
addtriangle (MD)
addpolygon(ポイント[,サーフェイス])
返す値:
ポリゴンID またはnil; 新規のポリゴンの識別子
ポイント:
ID[]またはポイントID; 新規ポリゴンのポイント
サーフェイス:
a d d t r i a n g l e ( ) は 、 パ ラ メータタイプの点で
addquad()と似ています。しかし、新規のポリゴンを作る
識別子
ために必要なポイントIDは4つではなく3つのみだという点で
文字列; ポリゴンが割り当てられるべきサーフェイ
異なります。
スの名称
addtriangle(ポイント)
返す値:
addcurve (MD)
addcurve()は、パラメータタイプおよびカウントの観点か
らは a d d p o l y g o n ( ) と同じです。しかし a d d c u r v e ( ) は、
与えられたポイントIDをポリゴンではなくモデラー曲線に返
ポイント:
polygon ID; 新規ポリゴンIDまたはnil
IDs[3]または3つの個々のポイントID; 三角形を
作るときに使うポイント
polyinfo (MD)
します。ポリゴンと曲線の違いは、曲線ポイント間の角度は
polyinfo()関数を使うと、個々のポリゴンについての情報
なめらかに補間されますが、ポリゴンポイント間の角度は厳
を集められます。polyinfo()は、可変数のアイテムを返し
密に線形だという点です。閉じた曲線を作るには、与えられ
ますが、その最初の要素はつねにポリゴンが割り当てられる
た開始点と終了点を重ねます。
サーフェイス名になります。他の要素は、ポリゴンを作って
ディスク内にあるgears.lsというスクリプト例は、
いる個々のポイントIDです。
addpolygon()とaddcurve()の両者を使った好例です。
オブジェクト内のすべてのポリゴンに同じ数のポイントがあ
るわけではないので、ポリゴンのポイント計数は、ポリゴン
addcurve(ポイント[,サーフェイス])
返す値:
により異なります。ポリゴンが持っているポイント数を判断
ポリゴンID またはnil; 新規の曲線の識別子
するために、polypointcount()関数(後述)を使って適
ポイント:
ID[]またはポイントID;新規の曲線のポイント識別子
サーフェイス: 文字列; 曲線が割り当てられるサーフェイスの名称
切なサイズの配列を割り当て、polyinfo()の戻り値を保持
します。
addquad (MD)
polyinfo(ポリゴン)
addquad()を使うと、四辺形(4ポイント)ポリゴンをオブ
返す値:
ジェクトのメッシュデータに追加できます。ポイント I Dは
個々に与えられますし、4つの要素の配列でも与えられます。
ポリゴン:
array[]; さまざまなサイズの配列で最初の要素
はサーフェイスの名称残りの要素はポイントID
ポリゴンID; 情報を知りたいポリゴン識別子
polypointcount (MD)
p o l y i n f o ( )に関連して p o l y p o i n t c o u n t ( )を使うと、
ポリゴンが持っているポイント数を設定できます。
–46–
polyinfo()が返す情報を保持するための配列のサイズを決
す。rempolygon() の場合は、ポリゴンを形成するポイン
めるときにこの情報が必要になります。たとえば、次のよう
トは削除されず、メッシュデータの一部として残ります。
になります。
status rempoint(ポイント)
例
ポイント:
ポイントID; 削除されるポイント
・・・
var pcount = polypointcount(polygons[x]);
status rempoly(ポリゴン)
var ppoints[pcount + 1];
ポリゴン:
ポリゴンID; 削除されるポリゴン
// surface name[1]のアカウント
ppoints = polyinfo(polygons[x]);
pointmove (MD)
・・・
pointmove()は、ポイントのベクトル位置を変更します。
status pointmove(ポイント,位置)
プロトタイプは次のようになります。
polypointcount(ポリゴン)
返す値:
整数; ポイント計数
ポリゴン:
ポリゴンID; 対象のポリゴンID
整数[3],ベクトルまたは数値; ポイントの新規の位置
polysurface()を使うと、 LScriptがポリゴンサーフェイ
スの名称を再割り当てします。
pointinfo()は、3D空間内でポイントが存在する位置を返
status polysurface(ポリゴン,サーフェイス)
します。
ポリゴン:
pointinfo(ポイント)
ポイント:
ポイントID; 移動するポイントのID
位置:
polysurface (MD)
pointinfo (MD)
返す値:
ポイント:
サーフェイス:
vector; ポイントの位置
ポイントID; 対象のポイントの識別子
ポリゴンID; 変更するポリゴンのID
文字列; ポリゴンが割り当てられるサーフェイスの
名称
polypoints (MD)
polynormal (MD)
polypoints()を使うと、ポイントの新規セットをポリゴ
polynormal()は、指定したポリゴンの法線ベクトルを返
ンに割り当てられます。ポリゴンを形成する元のポイントは
します。
自動的には削除されないので、不要の場合は手動で、
rempoint()を使って削除します。
polynormal(ポリゴン)
返す値:
ベクトル; ポリゴンの法線ベクトルまたはnil
ポリゴン:
ポリゴンID; ポリゴンの識別子
status polypoints(ポリゴン,ポイント)
rempoint, rempolygon (MD)
rempoint()およびrempolygon()は、それぞれポイント
またはポリゴンをオブジェクトメッシュデータから削除しま
–47–
ポリゴン:
ポリゴンID; 変更するポリゴンID
ポイント:
ポイントID[]; ポリゴンの新規ポイント
LightWave Layoutコマンドおよび関数
レイアウトジェネリックスクリプト以外、レイアウトのスク
リプト処理は、逆に L i g h t W a v eレイアウトが終了するまで、
レイアウトのLScript
あるいはプラグインパネルからレイアウトLScriptを明示的に
レイアウトの LScriptシステムは、プラグインプロトタイプの
非アクティブにするまでアクティブ状態のままになりますが、
機能をLightWaveレイアウトに持ち込むように設計された5つ
1つのL S c r i p tは一度だけしか起動されないようにする、新し
のLightWaveレイアウトプラグインで構成されます。新しい
いスクリプト実行方法を提供します。このスクリプトはLight-
プラグインでは次の5つのプラグインアーキテクチャを使用で
Waveレイアウト内でユーザが他の関数を実行している間もア
きます。
クティブになったままです。LightWaveレイアウトスクリプ
トは、この種の協調操作を行うように設計されています。
イメージフィルター
(ls-if.p)
オブジェクトリプレイスメント
(ls-ro.p)
ディスプレイスメントマップ
(ls-dm.p)
アイテムアニメーション
(ls-pt.p)
は状況に対応して随時呼び出されるよう設計された関数です。
レイアウトジェネリック
(ls-gn.p)
このようなコールバック関数は起動されるまで、「スリープ」
この協調した実行を容易にするため、レイアウトLScriptのス
クリプト処理は「コールバック」関数の概念を中心に据えて
います。コールバック関数は、通常、特定のイベントあるい
状態になっており、 C P Uの時間を取ることもなく、 L i g h tWaveレイアウトの処理にも影響しません。
ここから先へ進む前に
モデラーL S c r i p tの実行フローは非常に直線的です。実行は
レイアウトのLScriptはLScriptコアエンジンで使用でき
る機能を基盤として構築されているので、LScriptの開発に使
用するLScript言語あるいはテクニックをよく知らない場合は、
先にこのマニュアルの前節をもう一度読み直しておくことを
main()関数から開始され、介入ロジックあるいは関数の呼
び出しがあればそれを実行して、 main()関数が returnス
テートメントあるいは関数の論理的な終わりに到達して終了
すると、実行の終了に到達します。
お勧めします。
一方、レイアウトLScriptの実行フローは大きく異なります。
レイアウトLScriptにはスクリプトに対してきちんと定義され
レイアウトのスクリプト構造
ている実行ポイントが1つだけでなく、多数存在しています。
モデラーLScriptでは、スクリプトは完結したプログラムと同
事実、レイアウトL S c r i p tは1つのファイル内に個別のスクリ
様に実行されるように作成し、スタート、ボディ、エンドを
プトが多数存在すると考えることができます。レイアウトは、
明確に定義します。モデラー LScriptが実行終了位置に達する
と、再度そのL S c r i p tのプラグインを特定して要求するまで、
LightWaveモデラーはそのスクリプトを呼び出しません。ま
他のスクリプトを実行したり、他のスクリプトの支援を受け
たりすることなく、これらの「個別」スクリプト(関数)を随
時呼び出すことができます。
た、モデラー LScriptを実行中は、そのスクリプトが終了する
前にも述べましたが、レイアウトジェネリックスクリプトは
までその他の処理は実行されません。この種のオペレーショ
ンは、「 モ ー ダ ル 」 あ る い は 「 同 期 」 と 呼 ば れ て い ま す 。
Microsoft Windowsで使用されているグラフィックスを含め、
グラフィックスのダイアログボックスの多くは、この方法で
このメカニズムの例外です。この例外となっている理由は、
レイアウトジェネリックプラグインがレイアウトコンポーネ
ント(カメラ、メッシュオブジェクト、ライトなど)に関連
付けられておらず、そのため、アニメーションのフレームの
操作します。
生成には関わらないからです。レイアウトジェネリックスク
–48–
リプトにはエントリが1ポイントだけしかなく、この関数を用
destroy( )
いて実行を開始、終了するという点では、モデラースクリプ
スクリプトがプラグインパネルから非アクティブ化されたと
トとほとんど同じです。しかし、レイアウトジェネリックス
き、あるいはメモリから削除された時に一度だけ呼び出され、
クリプトは、その他のレイアウトスクリプトが使用している、
スクリプトの「クリーンアップ」処理の実行に使用します。
アーキテクチャを特定しないレイアウトコンポーネントすべ
てにアクセスできます。レイアウトジェネリック LScriptにつ
save( )
いては、このページでこれから詳細に説明します。
ユーザによってシーンファイルがディスクに保存されるとき
に呼び出されます。このとき、スクリプトは、シーンをLight-
これらのメカニズムを理解しておくことが、次の説明を理解
Waveレイアウトに再ロードされる際に、復元したいスクリプ
するには欠かせません。さらに理解を深めるため、この機会
ト関連の値があれば、それを格納することができます。この
に、例示されているスクリプトをご覧になることをおすすめ
関数は、シーン(A S C I I)ファイル、あるいはオブジェクト
します。
(バイナリ)ファイルで、シーンをディスクに保存するたびに
共有関数
呼び出されます。
各プラグインアーキテクチャはそれぞれ特定のコールバック
Load( )
関数を必要としますが、各レイアウトスクリプトは、アーキ
シーンファイルあるいはオブジェクトファイルから以前に保
テクチャにかかわらず、LightWaveレイアウトが呼び出せる
「共通の」エントリポイントを1つ、あるいは複数提供します。
存しているスクリプト関連値を復元する際に使用します。
これらの共通関数は、すべてオプションで、スクリプトでそ
options( )
れらを省略した場合に、レイアウトLScriptは、LightWaveレ
スクリプトの「オプション」ボタンが選択されると呼び出さ
イアウトの(「空」の)内部バージョンを提供します。
れます。モデラー LScriptで使用できるものと同じ標準リクエ
次のような共通関数があります。
スタ関数を使用して、ユーザインタフェースを生成でき、ユ
ーザはこれを用いて操作パラメータを変更できます。リクエ
process( )
スタダイアログを正常に作成するには、LightWave Panel Ser-
こ の コ ー ル バ ッ ク 関 数 は 、(モデラースクリプト処理に
vices Global-Classプラグインが使用できる状態でなければな
main()と類似した関数があれば)スクリプトのメインの処
りません。LW Panel Servicesプラグインを用いると、レイア
理を実行する際に使用します。これは何度でも呼び出すこと
ウトスクリプトは、付録Cで説明する、複数の「拡張」コントロ
ができます。
ールタイプを提供できます。
create( )
レイアウトスクリプトは、これらの「共通」関数の中の起動し
ておきたい任意の関数を定義できます。繰り返しますが、ス
スクリプトを読み込んだときに、LScriptコアエンジンがスク
クリプト内の共通関数に欠けている関数があれば、レイアウ
リプトの処理を正常に終了した直後に一度だけ呼び出されま
トScriptはデフォルトの動作(つまり、代わりに空の内部関数
す。これは、スクリプトの「スタートアップ」処理を実行しま
の呼び出し)を行います。これは、 process()関数の場合
す。
も同じです。 レイアウトジェネリックはこれらの標準関数と
は違います。レイアウトジェネリックスクリプトは1つの必須
関数、 generic()があり、ここでは、スクリプトを起動す
–49–
ると処理が発生します。詳細については、このページのレイ
イアウト内のオブジェクト選択パネルでユーザに表示される
アウトジェネリック LScriptの節を参照してください。
名前と一致していなければなりません。
名前のついたオブジェクトはライト、メッシュデータ、ある
レイアウトグローバル
いはボーンを含むことができます。
レイアウトLScriptはレイアウトスクリプトが処理中に使用で
filllight = getfirstitem("FillLight");
きるさまざまな「グローバル」値を設定します。これらの値
は読取専用(つまり、値の割り当て不可)で、スクリプトで
ボーンへのアクセス識別子がないことに気付いていることで
ローカルに宣言したときと同様にアクセスできます。
しょう。その理由は、ボーンオブジェクトはメッシュオブジ
現在レイアウトスクリプトで使用できるグローバル値は以下
ェクトの子オブジェクトであると考えられ、ボーンだけでは
のとおりです。
存在し得ないためです。ボーン情報は、親のメッシュオブジ
INSTANCE
プラグインアーキテクチャに関係なく、スクリプトの各
ェクトを経由して発生しなければなりません。ボーンオブジ
インスタンスが固有であることを保証する識別子を表す
ェクトは必然的に LScriptのメッシュオブジェクトのデータメ
読取専用文字列です。
ンバーとなります。
名前が示すとおり、 getfirstitem() は指定タイプのオブ
シーンのパブリック情報
ジェクトのリスト内にある(L i g h t W a v eレイアウトに従い)
最初のオブジェクトを返します。しかし、現在のシーンに指
getfirstitem()
定タイプのアイテムが全くない場合は、 getfirstitem()
レイアウトLScriptスクリプトにはシーンに含まれるパブリッ
ク情報へのアクセスがあります。メッシュ、ボーン、ライト、
カメラおよびシーンの各設定値に関するパブリック情報を利
はnilを返します。次のコードの断片はシーンで現在定義さ
れているライトの順次スキャンを開始する際に
firstitem()を使用する方法を示しています。
用できます。
例
この情報にアクセスするには getfirstitem()レイアウト
・・・
LScript関数を用います。
light = getfirstitem(LIGHT);
getfirstitem()は目的のタイプの最初のオブジェクトを
表す値を返します。 getfirstitem() にプル対象のオブジ
if light != nil then
ェクトリストを示すパラメータ値(便宜上レイアウトLScript
begin
// すべてのライトをスキャンする
で事前定義済み)を指定して使用できるオブジェクトタイプ
・・・
から選択します。事以下のような前定義済みの値があります。
MESH
使用可能なレイアウトメッシュオブジェクトから選択
LIGHT
定義済みレイアウトライトソースから選択
CAMERA
レイアウトカメラを表す値を取得
SENE
シーン設定値に関する情報を含む値を取得
get-
end
else
// we’re animating by Braille...
・・・
getfirstitem()が返すデータの型は、返されるレイアウ
getfirstitem()は、現在レイアウトに存在しているオブ
トオブジェクトにインタフェース、あるいはラッパーを提供
ジェクトの名前を表す文字列も受け付けます。この名前はレ
するよう設計されている、内部LScriptオブジェクトタイプの
–50–
インスタンスです。通常の LScriptデータ型(文字列、整数な
ェクトを返します。例を挙げると、レイアウトLScriptスクリ
ど)とは異なり、このデータ型はアライブ の状態です。レイ
プトでレイアウトライトオブジェクトのトラバースを達成す
アウトオブジェクトに関連付けられたデータへのアクセスを
る場合を見てみましょう。
提供するだけでなく、多くの場合、これらのオブジェクトイ
light = getfirstitem(LIGHT);
ンスタンス はレイアウトオブジェクトあるいはデータに何ら
while(light != nil)
かの操作を実行する際に呼び出す関数を提供します。レイア
{
ウトオブジェクトに対するこれらのラッパーはLScriptではレ
・・・このライトのインスタンスを処理するコード・・・
イアウトオブジェクトエージェントと呼びますが、このマニ
light = light.next();
ュアルでは単にオブジェクトエージェントと略しています。
}
ファイルオブジェクトと呼ばれるLScriptのデータ型もオブジ
ェクトエージェントの1タイプで、ディスクファイル用のエー
getfirstitem()が返した、(あるいは別のオブジェクト
ジェントとして使用されます。
エージェントを返すすべてのオブジェクトエージェントメソ
getfirstitem()は最初のレイアウトオブジェクトのオブ
ッドが返した)各オブジェクトエージェントは、次の共通メ
ジェクトエージェントを返しますが、ランダムにアクセスす
ソッドに応答し、次の共通データメンバーを含みます。
るレイアウトオブジェクトの機能はありません。また、リス
parent
ト内の次のレイアウトオブジェクトを返す、
get-
このレイアウトオブジェクトの親と考えられる、レイア
ウトオブジェクトを表すオブジェクトエージェントを指
し示します。
(なければnil)
firstitem()のコンパニオン関数もありません。では、同
target
じ型のその他のオブジェクトにアクセスするにはどうすれば
このレイアウトオブジェクトのターゲットとして指名さ
れたレイアウトオブジェクトを表すオブジェクトエージ
よいのでしょうか。
ェントを指し示します。(なければnil)
一度、リスト内の最初のオブジェクトエージェントを取得す
type
ると、そのクラスのレイアウトオブジェクトに順次アクセス
する機能を持つことができます。コールから
getf i r s t i t e m ( )に返される各オブジェクトエージェントは、
たとえやり方が異なっていても、各オブジェクトエージェン
別する、定数値を保持します。
goal
ェントを指し示します。
(なければnil)
name
な純粋なオブジェクト指向言語では、これらの共通な方法は
このレイアウトオブジェクトのゴールとして指定されて
いるレイアウトオブジェクトを表すオブジェクトエージ
トが同じ機能を実行できる共通関数(あるいは「メソッド」)
を提供(または、「エクスポート」)します。Smalltalkのよう
このレイアウトオブジェクトのタイプ(メッシュ、ボー
ン、ライト、カメラ、あるいはシーンのいずれか)を識
(レイアウトオブジェクトリストに現れる)このレイア
ウトオブジェクトの名前を表す、文字列を保持します。
オブジェクトが認識し、応答する「メッセージ」として知ら
param(state,time)
指定"time"インデックスの間の、特定レ
れています。異なる別の「クラス」(オブジェクトの定義)の
イアウトオブジェクトの状態の値を表す3 つの数値からな
インスタンスが同じメッセージに応答すると、「多態」と考え
る配列を返します。状態値はPOSITION(オブジェクト
られます。
座標の位置)
、
RIGHT,UP,FORWARD,ROTATION,SCALING,
各オブジェクトエージェントがエクスポートする、このよう
なメソッドは " n e x t " と呼ばれます。 n e x t ( ) メソッドは、
(LScript オブジェクトエージェントインスタンスとして)同
じオブジェクトカテゴリーリスト内の次のレイアウトオブジ
–51–
PIVOT,WPOSITION(「ワールド」座標の位置)の1
つになります。
limits(state) 特定のレイアウトオブジェクト状態
(POSITION,RIGHT,UP,FORWARD,ROTATION,
SCALING,PIVOT,WPOSITION)について既に設定
されている最低[エレメント1-3]限度および最大[エ
レメント4-6]限度を表す6個の数値からなる配列を返
のレイアウトオブジェクトに割り当てられたレイアウト
けではないので、オブジェクトエージェントはこれらのデー
を表す整数値か、そうでない(つまり、カメラ)場合は
タメンバーのサブセットだけを提供し、エクスポートしたメ
nilが入ります。
ソッドのサブセットに応答します。たとえば、シーンという
該当する場合は、レイアウトオブジェクトのポリゴン数
タイプのオブジェクトエージェントは、これらのメソッドの
を表す整数値か、妥当でない(つまり、カメラ)場合は
多くに対して nilを返し、カメラというオブジェクトエージ
nilが入ります。
ェントにはポイントあるいはポリゴンがありません。
shadhows[] レイアウトオブジェクトの現在のシャドウオプションを
表す3 つのブーリアン値からなる配列を保持します。
前にリストしたエクスポートしたオブジェクトエージェント
メソッドの多くは、「タイムインデックス」として提供する必
[1] == "セルフシャドウ"がオンの場合はtrue、オ
フの場合はfalse
[2] == "キャストシャドウ"がオンの場合はtrue、
オフの場合はfalse
[3] == "レシーブシャドウ"がオンの場合はtrue、
オフの場合はfalse
要のあるパラメータを受け取ります。このインデックス値は
シーンに含まれるアニメーションフレームの特定スパンが開
始してからの(時間で表される)オフセットを示します。目
的のタイムインデックスを計算するには、フレームナンバー
dissolve(time)
このレイアウトオブジェクトが指定された
"time"インデックスにディゾルブされるパーセント
(1は100%)を返します。
同じカテゴリーのリストにある次のレイアウトオブジェ
クトを返します。レイアウトオブジェクトがない場合は、
nilを返します。
firstChild() このレイアウトオブジェクトに属する最初の子オブジ
nextChild()
クトエージェントメソッドのnext() を使用すると、こ
レイアウトオブジェクトすべてに、同じ型のデータがあるわ
pointcount 妥当であれば、レイアウトオブジェクトのポイントの数
next()
ーンとして指定されたレイアウトオブジェクトを表す、
最初のオブジェクトエージェントを返します(オブジェ
レイアウトオブジェクトのある(パスがある場合はパス
も含めた)ファイル名を表す文字列を保持します。
polycount
このレイアウトオブジェクトに割り当てられる最初のボ
ボーンすべてをトラバースできます)。
します。
filename
bone()
をシーンの1秒あたりのフレーム数で割ります。たとえば、1
秒あたり30フレームで163番目のアニメーションは(163/30)
秒タイムインデックス、つまり、5.43秒後にアニメーション
に入れられます。
インデプスのオブジェクト
オブジェクトエージェントすべては前述の共通データメンバ
ェクトとして指定されたレイアウトオブジェクトを表す
ーとエクスポートしたメソッドを共有しますが、特定のオブ
オブジェクトエージェント返します。(レイアウトオブジ
ジェクトエージェントにはそれ以外のデータメンバーとメソ
)
ェクトがなければ、nil を返します。
ッドがあります。この理由は、レイアウトオブジェクトは、
このレイアウトオブジェクトの子として指定されたレ
イアウトオブジェクトを表す次のオブジェクトエージェ
ントを返します。
(レイアウトオブジェクトがなければ、
nilを返します。)
その機能に特有のデータを含んでいることが多い(たとえば、
カメラにはボーンにとっては意味のないズームファクタがあ
るように)ので、オブジェクトエージェントはレイアウト
LScriptのプログラマーにアクセス方法、そしてできればその
エリアを変更する方法を提供しなければなりません。
–52–
本書の執筆時には、L i g h t W a v e 3 Dバージョン5がリリースさ
coneangles[] これがスポットライトタイプであれば、このライト用
のコーン角度を表す、2つの浮動小数値からなる配列を保
持します。この最初のエレメント[1]はスポットライト
れていますが、この節で説明するすべてのデータメンバーは
読取専用で使われます。これらを変更すると、レイアウトオ
コーンの総角度の半分としての半径を表し、エレメント
ブジェクト自体に影響しませんが、スクリプトが実行される
[2]はスポットライトのソフトエッジの角度幅を示しま
と実行時エラーが発生します。
す。
ボーン
カメラ
flags[]
ボーンの現在のオプションを表す2つのブーリアン値から
なる配列を保持します。
focallength(time)
focaldistance(time) 指定"time"インデックスのカメラのフォ
ーカルディスタンスを表す浮動小数値を返します。
特定ボーン状態の値を表す3つの数値から
fstop(time)
UP、 FORWARD、ROTATION、SCALING、PIVOT、
WPOSITION、(「ワールド」座標位置)のいずれかにな
指定"time"インデックスのカメラのf-stop 設定
値を表す浮動小数値を返します。
blurlength(time)
fovangles(time)
restlength ボーンの残りの長さをメートルで表す、浮動小数値が入
指定"time"インデックスのカメラのブラ
ーレングスを表す浮動小数値を返します。
ります。
指定"time"インデックスのカメラの視野
角度を表す浮動小数値を返します。最初のエレメント
ります。
[1]は、水平角度を表し、第2のエレメント[2]は、垂
innerlimit ボーンの内径限度値を表す浮動小数値が入ります。(フラ
グ[2]がtrueの場合のみ有効)
outerlimit ボーンの外径限度値を表す浮動小数値が入ります。(フラ
グ[2]がtrueの場合のみ有効)
ライト
ambient(time) 指定"time"インデックスにグローバルアンビエン
トライトのRGB カラー値を表す3 つの整数値からなる配
直角度を表します。これらの角度(ラジアン)はカメラ
の向いている方向を中心にして測定します。
シーン
name
このシーンの名前を表す文字列を保持します。
filename
このシーンのファイル名を表す浮動小数値を保持します。
totalpoints
シーン内のメッシュポイントの合計数を表す整数値が
入ります。
列を返します。
totalpolygons シーン内のメッシュポリゴンの合計数を表す整数値が
このライトのタイプ(無限遠光、点光源、スポットライ
入ります。
トのいずれか)を識別する定数(読取専用)の整数値を
rendertype シーンで発生するレンダリングのタイプ
(WIRERENDER、QUICKRENDER、
REALISTICRENDERのいずれか)を識別する定数(読
保持します。
color(time)
指定"time"インデックスのカメラの被写
界深度を表す浮動小数値を返します。
なる配列を返します。状態値はPOSITION、RIGHT、
type
指定"time"インデックスのカメラの倍率
を表す浮動小数値を返します。
[1] == ボーンがアクティブであればtrue、その以
外はfalse
[2] == ボーンに制限があればtrue、それ以外は
false
restparam(state)
zoomfactor(time)
指定"time"インデックスのライトのRGBカラー値
を表す3つの整数値配列を返します。
取専用)整数値を保持します。
このライトのシャドウタイプ(SHADOWRAYTRACE 、
renderopts[] シーンの現在のオプションを表す8つのブーリアン値
SHADOWMAP、SHADOWOFFのいずれか)を識別する
からなる配列を保持します。
定数(読取り専用)の整数値を保持します。
–53–
[1] == x0
[1] == シャドウトレーシングがアクティブの場合は
true
[2] == y0
[2] == リフレクショントレーシングがアクティブの
[3] == x1
場合はtrue
[4] == y1
[3] == リフラクショントレーシングがアクティブの
場合はtrue
[4] == フィールドレンダリングがアクティブの場合
はtrue
[5] == リバースフィールドレンダリングがアクティ
ブの場合はtrue
[6] == モーションブラーがアクティブの場合は
true
リクエスタインタフェースの拡張
options()関数の中で、レイアウトスクリプトはモデラー
LScriptが使用するリクエスタコードと同じリクエスタコード
を使用できます。事実、リクエスタコードは修正を行わなく
てもスクリプト間で転送できます。しかしモデラーとは異な
り、LightWaveレイアウトコードにはユーザが作成したプラ
[7] == デプスオブフィールドがアクティブの場合は
true
グインを使用可能にする、インテグラルインタフェースコー
ドがありません。代わりに、レイアウトはPanel Servicesプラ
[8] == リミテッドリジョンがアクティブの場合は
true
グインを採用して、ユーザが作成したプラグインにインタフ
ェース機能を提供します。LScriptは、Panel Servicesプラグイ
framestart レンダリング開始番号を表す整数値が入ります。
franeend
レンダリング終了番号を表す整数値が入ります。
framestep
フレームステップ値を表す整数値が入ります。
fps
シーンの1秒あたりのフレーム数を表す整数値が入りま
ンを利用して、独自のリクエスタ機能を容易に実現します。
Panel Servicesは、LightWave3Dモデラーにある機能にさらに
機能を追加するコントロールを使用可能にするので、レイア
ウトスクリプトは新しい関数としてこの機能をレイアウトス
す。(デフォルトは30)
クリプトプログラマーに渡します。これらの新しいコントロ
framewidth レンダリング対象のフレームの横ピクセル数を表す整数
ールは「標準外」とみなされますが、レイアウトLScript内で
値が入ります。
frameheight
レンダリング対象のフレームの縦ピクセル数を表す整
数値が入ります。
pixelaspect
シーンのピクセルアスペクトレシオ(ピクセル縦横比)
を表す浮動小数値が入ります。
minsamplesperpixel
設計されているので、他のコントロールと同様に機能します。
Panel Servicesはプラグインなので、ユーザのLScriptがリクエ
スタパネルを出そうとするときに、そのプラグインが利用で
きない可能性が残ります。重要なプラグインが存在しないこ
とを検出する機能を、スクリプト作成者に提供するには、
現在のレンダリングオプションに基づい
た、最終イメージでの1 ピクセルあたりの最低サンプル数
reqbegin()コマンドをレイアウトLScript内で拡張してお
を表す整数値が入ります。
き、trueまたはfalseの論理値を返してPanel Servicesプラ
maxsamplesperpixel 現在のレンダリングオプションに基づい
た、1ピクセルあたりの最大サンプル数を表す整数値が入
ります。
limitedregion[]
グインの存在を示すようにしなければなりません。論理値
trueは、プラグインが存在することを示します。このインジ
ケータを使用するとスクリプトからリクエスタを表示するた
シーンのリミテッドリージョンエリアの場
所を表す、4個の浮動小数値からなる配列を保持します。
–54–
めの準備ができているかどうかを判断できます。
ベクトル addhsv(hsv,title)
例
・・・
カラー成分に入力する3つの数値入力フィールドと、入力値を
if(!reqbegin("My Requester"))
組み合わせ表示するプレビューエリアを含むコントロールを
{
作成します。
error("Requester support unavailable");
"hsv"は、'x','y','z'位置の色相、彩度、明るさというカラー成
return;
分を表すベクトル値です。この値はそれぞれ、0から255の整
数となります。
}
"タイトル"は、コントロールのラベルを表す文字列値です。
・・・
Panel Servicesをサポートするため、5つの新しいコントロー
(オブジェクトエージェント) additems(タイトル)
ル作成コマンドをレイアウトLScriptコマンドセットに追加し
カメラとすべてのライトを含めて、シーンで現在使用できる
オブジェクトのドロップダウンリストであるコントロールを
ました。これらの関数はレイアウトスクリプトでしか使用で
作成します。このコントロールの戻り値は、選択されたLight-
きません。モデラーLScriptには、これらのコントロールコマ
Waveオブジェクトを表すオブジェクトエージェントとなりま
ンドと同等のPanel Servicesはありません。
すが、オブジェクトか選択されていない時はnilとなります。
文字列 addfilename(ファイル名, タイトル)
"タイトル"は、コントロールのラベルを表す文字列値です。
テキスト編集フィールドとファイルリクエスタダイアログボ
ックスを表示するプッシュボタンを含むコントロールを作成
アーキテクチャの詳細
します。ファイルリクエスタから返された選択肢はテキスト
これまでに、すべてのレイアウトスクリプトに共通なメソッ
編集フィールドに置かれます。
ド、関数、データを説明しましたので、スクリプトプログラ
"ファイル名 "は、コントロールのファイル名編集フィールド
マーに提供されている拡張機能に対する特定プラグインアー
の初期値を表す文字列値です。
キテクチャを検討してみます。
"タイトル"は、コントロールのラベルを表す、文字列値です。
LightWave3Dがプラグインに対して公式に使用可能としてい
る内部データ構造について説明するので、ユーザが3Dレンダ
ベクトル addrgb(rgb,タイトル)
リングシステムで採用しているデータ構造とメカニズム、な
カラー成分に入力する3つの数値入力フィールドと、入力値を
らびに現在業界で使用されている、一般的なコンピュータグ
組み合わせて表示するプレビューエリアを含むコントロール
ラフィックファイルフォーマット(例:Targa)について詳し
を作成します。
いことを想定しています。
"rgb"は、'x','y','z'位置の赤(Red)、緑(Green)、青(Blue)とい
うカラー成分を表す値です。この値はそれぞれ、0から255ま
LS/IF(イメージフィルタ)
での整数となります。
LS/IFプラグインは、LightWave3Dがレンダリングを完了した
"タイトル"は、コントロールのラベルを表す文字列値です。
フレーム(イメージ)の後処理に使用します。
LScriptプラグインはレンダリングした結果生成された赤、緑、
青のカラー値とアルファチャネル値の入ったレイアウトが保
守を行う、内部データバッファにアクセスします。LS/IFは表
–55–
示可能なフレームを表す各カラー値にエフェクトを適用する
SPECIAL
この値はこのフィルタだけに使用され、サーフェイスご
際に使用します。
とにユーザが割り当てる値です。これは、特定サーフェ
イメージバッファの選択
設計され、また、ユーザがバッファに0から255までの
イスの後処理エフェクトを起動する際に使用するように
値として割り当てたパーセントは、ここに表示されます。
LS/IFは、flags()と呼ばれるオプションのスクリプトをサ
ポートします。スクリプトはこの関数を用いて、使用可能な
LUMINOUS,DIFFUSE,MIRROR,TRANS,RAWRED,RAWGREEN,
バッファの中でスクリプトがどのバッファにアクセスできる
RAWBLUE
かに関してレイアウトと通信します。LightWaveのレイアウ
これらの8つのバッファはシェーディングをする前のサー
フェイスパラメータの未処理値です。
トはこのメカニズムを使用して、メモリを保護します。スク
SHADING
リプトが特定バッファを必要としない場合は、レイアウトは
このバッファは、イメージの未処理形状に適用される拡
散シェーディングのピクチャです。
メモリと CPUタイムを割り当てて、ユーザに対してこれらの
SHADOW
このバッファは最終イメージ内で影ができる場所を示し
バッファがコピーできるようにする必要がありません。 35
ます。これはまた、シーン中のライトにイメージ内のど
2
の部分が見えるかを示す、イルミネーションマップとし
ても考えることができます。
レンダリング作業の結果レイアウトが使用、あるいは作成す
GEOMETRY
る、異なるデータバッファは多数あり、使用しているLS/IFス
このバッファの値は視点ベクトルを用いたサーフェイス
ノーマルのドットプロダクトから計算されます。これは
クリプトはこれらのバッファのすべてあるいは任意のバッフ
イメージ内のオブジェクトの下にある形状に関すること
ァにアクセスする要求ができます。どのバッファを要求する
を示します。このバッファが255(または1.0 )の場合
かにかかわらず、すべての LS/IFスクリプトにはレイアウトが
は、サーフェイスはまっすぐカメラの方を向いており、
維持している赤、緑、青、アルファチャネルの各バッファへ
このバッファが0の場合は、サーフェイスはカメラに対し
の暗示的なアクセスが用意されていますので、明示的にこれ
て横向きになっています。
らのバッファを要求する必要はありません。
DEPTH
このバッファは、カメラプレーンからの各ピクセルの距
離を示すマップです。他のすべてのバッファとは異なり、
暗示的なバッファ(赤のみ、緑のみなど)という例外はあり
このバッファは浮動小数値で、アンチエリアシングある
ますが、すべてのレイアウトが維持するバッファは読取専用
いはモーションブラー処理をしません。
です。データを実際に変更したいバッファに対する修正にコ
ンテンツを反映させる場合に使用します。
LS/IFスクリプトがアクセスを要求できるバッファは以下のと
flags()
おりです。
関数がこれらの事前定義値を1つ以上返すと、スクリプトが使
RED,GREEN,BLUE,ALPHA
用可能になり、レイアウトバッファと通信することができま
これらのバッファは、すべてのスクリプトで使用でき、レン
す。事実、 flags()の目的は、1つあるいは複数の値を返す
ダリング済みフレームのR G Bの各値とアルファ値を個別に表
ことです。たとえば、次のコードは暗示バッファを要求して
します。すべての使用可能なバッファをオフにすることはで
単にCPUタイムを消費するだけのサンプルの flags()を示し
きますが、それだけしか変更はできません。他はすべて完全
ています。
に読取専用です。
–56–
LS/IFスクリプトは、赤、緑、青、アルファチャネルの各イメ
例
ージバッファデータにアクセスし、更新するための特殊な内
flags
部関数を呼び出せます。これらの関数は、1つのLS/IF関数に
{
対してのみ有効で、他のレイアウトスクリプトとは共有でき
return(RED,GREEN,BLUE,ALPHA);
ません。
//面白いのでデフォルトを選択
}
[]bufferline(bufferid,line)
示された垂直イメージ"line"の"bufferid"で識別されるバッファ
イメージバッファの処理
内の値を検索する際に使用します。"bufferid"は以前に説明さ
多くのレイアウトスクリプトと同様、LS/IFスクリプトの処理
れた(SPECIAL,DIFFUSE,REDなど)のバッファインジケータ
の中心点は process()関数で発生します。 process()関
の1つです。flag()関数で選択されていないバッファが要求
数はLightWave3D レイアウトが生成したアニメーションのす
された場合、実行時エラーが発生します。エレメントのカウ
べてのフレームについて一度だけ呼び出され、スクリプトが
ントが、 process()関数に渡す"width"パラメータと一致す
イメージピクセルに適用するように設計されている操作は、
るバッファ値の配列を返します。
その時点でイメージ全体にレンダリングされます。
[] floatline(bufferid,line)
LS/IFは呼び出されると process()関数に5つのパラメータ
この関数は、浮動小数点データ(現在のところDEPTHバッフ
を渡します。これらのパラメータはイメージ幅と高さ、レン
ァだけが適格)を含むバッファにアクセスする際に使用する
ダリング中の現在のフレーム番号などの情報を提供してレイ
アウトバッファ内のデータへのアクセスを支援するように設
こと以外は、bufferline()と同じです。
計されています。LS/IF process()に渡される5つのパラメ
setrbg(col,row,buf)
ータは次のとおりです。
イメージの指定行/列にある特定イメージピクセルの赤、緑、
width
生成イメージの幅(水平ラインの数)を示す整数値です。
青の値を設定する際に使用します。"buf"は赤([1])
、緑([2])
、
この値はユーザがレイアウトカメラ情報パネルで設定し
青([3])を表す3つのカラー値からなる配列です。
た値と等しくなります。
height
setalpha(col,row,bufval)
生成イメージの高さ(垂直ラインの数)を示す整数値で
す。この値はユーザがレイアウトカメラ情報パネルで設
イメージの指定行/列にある特定イメージピクセルのアルファ
定した値と等しくなります。
値を設定する際に使用します。
frame
生成イメージのフレームナンバーを示す整数値です。
start
このフレームの開始時間をタイムインデックス値として
processrgb(row,red,blue,alpha)
この関数は setrgb()とsetalpha() の関数の代わりをし、
表す浮動小数値です。
end
指定イメージ行の4つのバッファすべてを同時に処理します。
タイムインデックス値として表される、このフレームの
終了時間を表す浮動小数値です。
個別のバッファエレメントは、 setrgb()とsetalpha()
このインデックス値はフレームにレイアウトからモーシ
の場合のように一時に1バッファではなく、すべて同時に処理
ョンブラーを適用しない限り、開始時刻と同じです。こ
されるため、この関数ははるかに高速です。
の場合、開始時刻インデックスと終了時刻インデックス
LScript配列に関係するすべての場合と同様に、イメージ列/行
との差はそのフレームの「エクスポージャタイム」です。
インジケータとして使用する値は、各バッファ内の最初のエ
–57–
レメントが常時[1]という意味の"1ベース"にしなければなりま
キャッシュ処理を有効にしてしまうと、他のすべてのLS/IFコ
せん。ユーザが最初のエレメント[0]にアクセスしようとする
マンドと関数は本物のフィルタ処理を実行しているのと同様
と、実行時エラーが生成され、LS/IFスクリプトはそれ以上の
に使用できます。しかし、これらの関数の呼び出しはレイア
動作をしないように使用不可となります。
ウトでバッファ処理されたデータではなく、スクリプトイン
スタンス内のローカルデータを検索し、更新することに制限
イメージデータのキャッシュ化
されます。
名前の示すとおり、Image Filterプラグインは名前の示すとお
キャッシュ処理が有効になると、新しい内部イメージデータ
りフィルタです。データはレイアウトの一端から入り、レイ
を明示的に「フラッシュ」する必要はありません。スクリプ
アウトの他端から直接返されます。レイアウトレンダリング
トのprocess()関数が終了した時点で、LS/IFプラグインが
バッファ内のデータのコピーを検索するため、 b u f f e r-
自動的に修正済みデータのレイアウトへの更新を完全に実行
line()を呼び出す場合は、ユーザがその行を処理し、使用
します。
可能な処理コマンドのいずれかを使用してレイアウトに返さ
なければなりません。一般的な処理状況では、この修正済み
LS/IFロジックの流れ
データをレイアウトに渡すと、二度とアクセスすることはで
ここで、L i g h t W a v e 3 Dレイアウトから呼び出されるときに、
きません。同じスキャンラインを要求する bufferline()
LS/IFスクリプトを経由して渡されるコントロールの流れを検
の呼び出しを行っても、元の、修正していないスキャンライ
討してみましょう。
ンデータを返すだけです。ユーザが修正したデータは、ユー
LS/IFスクリプト内の処理シーケンスは一般に flags()関数
ザの手の届かない別のバッファに安全に、しかも永久にしま
から始まります。この関数はオプションで、flags()を実際
い込まれます。
にスクリプトで使用すると、 p r o c e s s ( ) 関数では赤、緑、
LS/IFは、レイアウトが提供するレンダリング済みイメージデ
青、およびアルファの各バッファだけが使用可能となります。
ータを取り出し、ローカルでキャッシュ化する、内部メカニ
わかりやすくするため、暗示バッファを選択する、スペース
ズムをスクリプト作成者に提供します。これにより、複数パ
を消耗するだけのflags()関数を呼び出してみます。
スでのイメージデータ処理、あるいはデータすべてを循環す
例
る必要なく、イメージの一部だけの処理などの手順が行えま
flags
す。このメカニズムは必ずしもLS/IFスクリプトの速度を改善
{
することはなく、むしろ、スクリプト作成者に便宜を提供し
return(RED,GREEN,BLUE,ALPHA);
ます。
}
このキャッシュ処理機能を有効にするには、LS/IFスクリプト
のprocess()関数の冒頭で次の関数を呼び出します。
スクリプトがアクティブになっていれば、レイアウトは
cache()
process()関数を呼び出して、レンダリング済みイメージ
に処理を追加しようとします。これは一般的にイメージがレ
この関数は、LS/IFスクリプトインスタンスにすべてのレンダ
ンダリングされた直後で、まだユーザに表示されておらず、
リング済みイメージデータをスクリプトのローカルメモリス
ディスクに保存もされていない時に発生します。次に、スク
ペースに置かせ、同一データに対して複数のアクセスを容易
リプトが各イメージの複製を必要とする場合の一般的な処理
にします。
のフローを示す、不完全なprocess()関数を示します。
–58–
内の結果を示す場所は、(一般的には、出力時に黒となる、各
例
チャネルにゼロを割り当てた)未定義値RGBになります。
process: width, height, frame, starttime,
endtime
モニタの使用
{
レイアウトLScriptプラグインの中での固有な、LS/IFはモデラ
out[3] = nil;
// レイアウトに返される新しい値を保持
for(i = 1;i <= height;++i)
スを提供します。Image Filterプラグインの内部で大半の処理
ーLScriptが提供するのと同様のプログレスモニタへのアクセ
が行われるので、仮想インジケータを使用して、処理の進行
{
red
具合をビューアにフィードバックします。
(アニメーションの
= bufferline(RED,i);
green = bufferline(GREEN,i);
1フレームごとに640x480の各イメージを1ピクセルごとに何
blue
らかの関数を実行しなければならないことを想像してみてく
= bufferline(BLUE,i);
ださい!)
alpha = bufferline(ALPHA,i);
次の関数は、レイアウトが提供するモニタアクセスを管理す
for(j = 1;j <= width;++j)
る際に使用します。見てのとおり、これらの関数の使用方法
{
はモデラーLScript内で提供される関数とほとんど同じです。
//バッファ値に関して何らかの操作を
//実行
moninit(steps)
・・・
モニタシステムを初期化し、処理タスクを完了するまでに必
setrgb(j,i,out);
要なステップ数を予測します。
setalpha(j,i,alpha[j]);
monstep([advance])
}
提供されるオプションの整数値により、モニタインジケータ
}
を次に進めます。引数がない場合は、アドバンス値は1となり
}
ます。
特定イメージピクセル、あるいはアルファチャネル値を変更
monend()
するかしないかにかかわらず、 cache()への呼び出しを用い
モニタシステムを終了します。
てキャッシュ処理を有効にしていないかぎり、 setrgb()と
setalpha()(あるいは、代わりにprocessrgb())を作
LS/PT(プロシージャルテクスチャ)
成しなければなりません。名前が示すとおり、LS/IFはイメー
(一般的にはシェーダーと呼ばれることの多い)プロシージャ
ジフィルタであり、他のすべてのフィルタと同様、何かの入
力を期待し、必要なものを通過させて、結果を出力します。
LightWaveのレイアウトは、赤、緑、青とアルファチャネル
の各バッファ内のすべてのピクセルがこのフィルタを通過し、
ルテクスチャは、特定の値に基づいてレンダリング時に計算
されるサーフェイスの表現です。L S / P Tはシェーダースクリ
プト処理プラグインで、サーフェイスに任意のテクスチャあ
完全なイメージを生成することを期待しています。ピクセル
るいは色を付ける際に使用します。
をレイアウトの出力に処理できなかった場合は、ユーザがそ
組み込まれたスクリプト例のBlotchは、サーフェイスに着色
の他を変更しているかいないかにかかわらず、最終イメージ
したスポットを作成します。
–59–
シェーダー関数
テクスチャの処理
LS/PTには、2つのLS/PTに特有なサポート関数があります。
すべてのレイアウトスクリプトの場合と同様、L S / P Tスクリ
プトの処理ポイントは、 p r o c e s s ( ) 関数です。この
init()
process()関数はピクセル単位で呼び出されます。
フレームのシーケンス開始時点で呼び出されます。テクスチ
LS/PTは、スクリプトの proces()関数に1つの引数を提供し
ャを正しく生成するために必要なスクリプト値を初期化しま
ます。この引数はオブジェクトエージェントのインスタンス
す。
で、シェーダーオブジェクトと呼ばれています。このオブジ
cleanup()
ェクトにはアクセス可能なデータメンバーとメソッドがあり
レンダリングシーケンスが完了した時点で呼び出されます。
ます(変更可能な場合もあります)
。
LS/PT シェーダオブジェクトには次のメンバ/メソッドがあり
newtime(frame,time)
ます。
現在のレンダリングシーケンス内の新しい時間の開始時に呼
び出されます。整数値" f r a m e "は現在のフレーム番号を示し、
sx
(読取専用)
(0,0)が左上隅を示す、ピクセル座標の最終イメージ内
"time"は現在のタイムインデックスを示します。
のスポットX位置を表す数値です。
sy
flags()
読取専用)
0,0)sが左上隅を示す、ピクセル座標の最終イメージ
内のスポットY 位置を表す数値です。
L S / P Tスクリプトは、変更対象サーフェイスのテクスチャの
属性をレイアウトに示す必要があります。以下の値の中から1
oPos[3]
つ、あるいは複数の値がflags()関数から返されます。
(読取専用)
オブジェクト座標のスポット位置の座標を表す数値です。
NORMAL
wPos[3]
(読取専用)
ワールド座標のスポット位置の座標を表す数値です。
COLOR
gNorm[3]
LUMINOUS
(読取専用)
ワールド座標系でのスポットのジオメトリックノーマル
DIFFUSE
を表す数値です。これは、そのスポットの未処理の法線
で、スムージングやバンプマッピングで改変されていま
SPECULAR
せん。
MIRROR
spotSize
TRANSPARENT
(読取専用)
おおよそのスポット直径を表す数値です。エッジに見え
ETA
るサーフェイスのスポットは細長いので、これは非常に
ROUGHNESS
に使用できます。
近い値です。これは、テクスチャのアンチエリアシング
RAYTRACE
raySource[3] (読取専用)
ワールド座標に入ってくるビュー処理対象のレイの原点
を表す数値です。これは、カメラになりますが、カメラ
LS/PTスクリプトが raytrace()メソッド(現在説明中)を
でなくてもかまいません。
活用する場合は、L S / P Tスクリプトは f l a g s ( )に返し値の
RAYTRACEフラグを組み込んでいなければなりません。
–60–
luminous
rayLength (読取専用)
このスポットに到達するまでの空間をビュー処理対象の
サーフェイスの明るさをパーセントで表す数値です。
レイが移動する距離を表す数値です。
cosine
(1.0 == 100%)
(読取専用)
diffuse
ビュー処理対象のレイとこのスポットの法線との間の角
サーフェイスのディフューズをパーセントで表す数値で
度に対する余弦を表す数値です。これは、このビューが
す。(1.0 == 100%)
どのように見えるか、およびスポットサイズがどの程度
specular
の概算値であるかを知る手段を提供します。
oXfrm[9]
サーフェイスのスペキュラリティをパーセントで表す数
(読取専用)
値です。(1.0 == 100%)
オブジェクト座標からワールド座標への変換マトリクス
mirror
です。これは別の方法で計算することもできますが、速
wXfrm[9]
度を上げるためここに組み込み、主に方向ベクトルに使
サーフェイスのミラーリング(反射)をパーセントで表
用することを目的としています。
す数値です。
(1.0 == 100%)
transparency
(読取専用)
ワールド座標からオブジェクト座標への変換マトリクス
サーフェイスのトランスペアレンシーをパーセントで表
です。これは別の方法で計算することもできますが、速
す数値です。
(1.0 == 100%)
度を上げるためここに組み込み、主に方向ベクトルに使
eta
用することを目的としています。
objID
サーフェイスの屈折率をパーセントで表す数値です。
(読取専用)
(1.0 == 100%)
シェーディング対象のオブジェクトを表すオブジェクト
roughness
エージェントへのポインタです。
polNum
サーフェイスの粗さをパーセントで表す数値です。
(1.0
(読取専用)
== 100%)
シェーディング対象のオブジェクトのポリゴン数を表す
整数です。これは通常のメッシュオブジェクトではポリ
ゴン数ですが、メッシュ以外のオブジェクトの場合は他
直接見える色を設定するため、シェーダースクリプトは、1.0
のサブオブジェクト情報の場合もあります。
をとるluminousと、スポットの出力カラーである、colorを除
wNorm[3]
く、パラメータすべてをゼロに設定することができます。
ワールド座標のスポットの新しいジオメトリックノーマ
ルです。これを変更すると、ジオメトリ(バンプマッピ
ShaderObjectメソッド
ング)を変更しなくてもサーフェイスをでこぼこの感じ
ShaderObjectはサーフェイステクスチャを生成する際に使用
することができます。このシェーダーは、パータベーシ
する2つのメソッドを提供します。
ョンの後にベクトルを再度ノーマライズする必要があり
illuminate(ライト,位置)
ます。
この関数は、現時点で指定のライトから指定位置までの光線
color[3]
サーフェイスに使用する色の赤[1] 、緑[2] 、青[3]の
(color[1-3]およびdirection[4-6])を表す、6つの数値からなる
各パーセント値を表す数値です。ここで1.0 は100%を
配列を返します。ライトが指定のワールド座標位置を全く照
指します。
らさない場合は、戻り値はゼロになります。c o l o rは、(存在
すれば)シャドウからのエフェクト、フォールオフ、スポッ
–61–
トライトコーン、ライトとポイント間の透明オブジェクトを
oPos[3]
(読取専用)
組み込みます。
元の位置で処理されるポイントの位置を表す数値です。
raytrace(位置,方向)
ットを計算する際に使用します。
これらの値は変更されず、経過時間にもとづき、オフセ
この関数は、(ワールド座標の)指定方向の指定場所からの光
source[3]
線をトレースするために呼び出されます。この関数はray[1]の
現在のフレーム/タイムで処理されるポイントの新しい位
長さを現し、その direction[2-4]から入力されるカラーを表す、
置を表す数値です。
4つのエレメントからなる配列を返します。光線の長さが不定
の場合は-1から0です。使用される方向は外向きの方向で、単
ディスプレイスメントオブジェクトで提供されるメソッドは
位ベクトルに正規化されなければなりません。
ありません。
LS/DM(ディスプレイスメントマップ)
LS/IA(アイテムアニメーション)
LS/DMのプラグインは、指定フレームあるいは時間に基づき、
LS/IA、アイテムアニメーションプラグインを用いると、ユー
オブジェクトのポイントの位置を計算する際に使用します。
ザはアニメーションシーケンス中のオブジェクトの解釈に影
一回の呼び出しで処理が完了するLS/IFと異なり、LS/DMスク
響を及ぼすことができます。レイアウトが計算したオブジェ
リプトはポイントごとに呼び出されます。
クトの位置、回転、およびスケーリング、オーバーライドを
ディスプレースメント関数
変更できます。
LS/MDは次のディスプレースメント特有の関数を提供します。
モーションの処理
newtime(オブジェクト,フレーム,時間)
L S / I Aは p r o c e s s ( ) 関数に3つの引数を提供します。第2、
L S / P Tと同様、この関数は現在のシーケンス内で新しく時間
第3のパラメータは、現在の呼び出しに対する整数のフレーム
が開始するときに呼び出されます。 newtime()に提供され
番号と、数値のタイムインデックスです。最初の引数は
るパラメータは、処理対象のポイントを含むオブジェクトを
MotionObjectのインスタンスです。
表すオブジェクトエージェントと、フレーム番号を表す整数
LS/IA MotionObjectは次のオブジェクトメソッドを提供しま
と、現在のタイムインデックスを表す数値です。
す。
flags()
get(属性,時間)
この関数は、ディスプレースメントがワールド座標内で発生
この関数は指定"時間"の指定属性の値を表すベクトルを返しま
するか、あるいはオブジェクトのローカル座標内で発生する
す。"属性"は、 POSITION、ROTATION、SCALINGのいずれか
かを示す、2つの値のうちのいずれかを返します。
となります。"時間"は、ユーザの関心のあるタイムインデック
ディスプレースメントの処理
スです。ROTATIONの場合、値は「度数」です。SCALING値
L S / D Mの p r o c e s s ( )関数には1つの引数があります。この
は乗数で、1.0の場合は変更なしです。
引数は、ディスプレイスメントオブジェクトのインスタンス
set(属性,値)
です。
この関数は指定指定した属性( P O S I T I O N、 R O T A T I O N 、
LS/DM ディスプレイスメントオブジェクトには以下のデータ
SCALING)を新たなベクトル値にセットします。
メンバがあります。
–62–
LS/IA ディスプレイスメントオブジェクトには次のデータメ
curType
現在のレンダリング対象のタイプを示す定数値です。ス
ンバーがあります。
objID
(読取専用)
クリプトはこの値を調べて、対話型プレビューと実際の
(読取専用)
レンダリング時に異なるジオメトリを提供します。この
この特定プラグインを割り当てているオブジェクトエー
値はNONE、 PREVIEW 、RENDERのいずれかになり
ジェントへのポインタです。
ます。NONE は現在のタイムインデックスにジオメトリ
がロードされていないときに提示されます。PREVIEW
LS/OR(オブジェクトリプレイスメント)
は、レイアウトプレビューを生成中であることを示し、
LS/ORを用いると、フレーム単位でレイアウトのオブジェク
RENDERは完全なレンダリングを実行しているときに使
トを交換できます。
用されます。
newType
交換の処理
次のフレーム/タイムインデックスで実行されるレンダリ
LS/ORのプラグインの process()関数は引数を1個受け取り
ングのタイプを示す定数です。このメンバはNONE、
ます。この引数はリプレイスメントオブジェクトのインスタ
REVIEW、RENDERのいずれかです。
ンスです。 LS/ORのリプレイスメントオブジェクトは次のデ
curFilename(読取専用)
ータメンバを提供します。
objID
(読取専用)
現在ロードされているオブジェクトジオメトリファイル
(読取専用)
を表す文字列値です。ロードされているジオメトリがな
ジオメトリを交換する対象のオブジェクトを表
ければ、nilの場合もあります。
すオブジェクトエージェントです。
curFrame
newFilename
新しいタイムインデックスで、このアイテムのジオメト
(読取専用)
リとしてロードされている新しいオブジェクトファイル
現在ロードされているジオメトリのフレーム番号を表す
のファイル名を表す文字列値で、スクリプトが設定する
整数値です。
curTime
唯一のデータメンバです。新しいジオメトリのロードは、
(読取専用)
多大なオーバーヘッドを発生するので、新しいジオメト
現在ロードされているジオメトリのタイムインデックス
リが現在ロードされているジオメトリと異なるときにの
を表す番号です。
newFrame
み設定します。
(読取専用)
次のステップのフレーム番号を表す整数値です。新しい
LS/GN(レイアウトジェネリック)
フレームでオブジェクトが異なった外観になる必要があ
newTime
る場合は、新しいジオメトリをロードしなければなりま
最後の、レイアウトジェネリックスクリプト処理になりまし
せん。
た。LS/GNを用いると、シーンあるいはシーンのコンポーネ
ントと関連付けをしなくても、レイアウトの内部オブジェク
(読取専用)
次のステップのタイムインデックスを表す整数値です。
トとデータにアクセスできます。レイアウトジェネリックス
オブジェクトが新しいタイムインデックスで異なった外
クリプトはシーンのすべてのコンポーネントと設定値にアク
観になる必要がある場合は、新しいジオメトリをロード
セスでき、L S c r i p tエンジンに属するすべての関数とデータ
しなければなりません。ネットワークレンダリングはシ
ーケンシャルでない時刻と時刻の間でレンダラにジャン
(プリプロセッサ、リクエスタサポート、IPCキューなど)に
もアクセスできます。
プを発生させることもあるので、"curTime"および
"newTime"はシーケンスでない場合があります。
–63–
ロードされると、内部的にシーンファイルに名前を付けます。
ジェネリックスクリプトの構築
レイアウトジェネリックスクリプトはモデラースクリプトで
このオプション名はシーンの新しいファイル名となります。
使用するフォーマットと非常に類似しています。すべてのレ
このパラメータが提供されない場合は、代わりに "filename"パ
イアウトジェネリックスクリプトにおいて必須の関数が1つあ
ラメータが使用されます。
り、この関数は generic()と呼ばれています。レイアウト
savescene(ファイル名)
ジェネリックスクリプトが呼び出されると、この関数を用い
この関数は、レイアウトに現在ロードされているシーンをの
て実行が開始され、この関数が終了すると、スクリプトの実
パスを含んだファイル名を保存します。
行は完了します。
次に、現在レイアウトにロードしているオブジェクトの頂点
数をレポートする、単純なレイアウトジェネリックスクリプ
トを紹介します。
generic
{
if(!reqbegin("Point Count"))
return;
//パネルサービスプラグインがない場合
c1 = additems("Reference object");
if(reqpost())
{
if((item = getvalue(c1)) == nil)
return;
}
else
return;
reqend();
info("Object ",item.name,"
has",item.pointcount," points.");
}
ジェネリック関数
レイアウトジェネリックアーキテクチャは、レイアウトのシ
ーンを管理するための2つの関数を使用可能にします。
loadscene(ファイル名[,タイトル])
この関数は、レイアウトのシーンファイルとして示された"フ
ァイル名"をロードします。オプションの"title"パラメータは、
–64–
LScriptの拡張:ネイティブコードとのリンク
L S c r i p t言語はユーザ定義手順( U D F)をサポートします。
#define LSINTEGER
1
BMLコアエンジンの旧リリース(LScriptの前身)では、メイ
#define LSNUMBER
2
ンスクリプトの本体にあるか、あるいはBMLスクリプトライ
#define LSSTRING
3
ブラリファイルで宣言されているかにかかわらず、 U D Fは
#define LSVECTOR
4
BMLスクリプト処理言語だけで定義可能な手順だけに限定さ
#define LSFILE
5
#define LSNIL
99
れていました。
LScriptのコアエンジンは共有ライブラリ(Windows DLLある
いはUNIXの共有ライブラリ)を直接リンクして、ネイティブ
次に定義されたアイテムはLScriptとDLL関数との間で渡すデ
マシンコードで書かれたUDFのパワーと速度を利用できます。
ータを含む構造体です。
このネイティブコードはCあるいはC++ソースから作成します。
typedef struct _ls_var
この機能は複数のプラグイン機能を、たとえば、1つのプラグ
{
インに提供することによく似ています。
int
この文書の残りでは、Microsoft Windowsのダイナミックリ
type;
union
ンクライブラリー(D L L)を用いた共有ライブラリを説明す
{
ることに集中してゆきます。L S c r i p tのU N I Xバージョン下で、
double number;
共有ライブラリを作成する方法はプラットフォームにより異
const char *string;
なるので、最も普及したLightWave3Dプラットフォームを中
double vector[3];
心にして説明します。説明するテクニックのほとんどは
}data;
LScriptとリンク可能な共有ライブラリを生成する UNIXメソッ
}LS_VAR;
ドにも同様に適用できます。
Microsoft Windowsでは、LScriptスクリプトを用いてリンク
" t y p e "メンバーはファイルの冒頭に定義されたデータタイプ
するD L Lライブラリ機能を生成するために必要なステップは
(LSINTEGER、LSNUMBERなど)の一つを保持します。 "type"
複数あります。まず、LScriptインターフェイスメカニズムに
に基づき、"data"ユニオンメンバ、 "number"、"string"、ある
詳しくなければなりません。このメカニズムを用いるとユー
いは" v e c t o r "の一つからデータを抽出できます。ユニオンの
ザは実行中の LScriptを用いて直接対話できます。これは、コ
"number"メンバは実数値と整数値を包含する際に使用します。
ンパイルするWindows DLLソースファイルに組み込まなけれ
たとえば、データの"型"がLSINTEGERであれば、"number"メ
ばならない、"lscript.h"ヘッダーファイルに定義されます。
ンバの単純なキャストは整数値を抽出します。
ライブラリを作成する際に使用できるように、"lscript.h"ヘッ
ダーファイルには複数のアイテムが定義されます。最初に、
x = (int)・・・data.member;
LScriptとDLL関数とで渡されるデータタイプはマニフェスト
ヘッダーの次のエントリは、LScriptとの対話を希望するすべ
定数として提供されます。一部の複雑なLScriptデータタイプ
てのD L L関数が付加しなければならない関数プロトタイプで
はD L L関数では現在利用可能ではありませんが、次のデータ
す。DLL関数は、typedefを直接使用することはなく、関数
タイプを用いるとかなり多くのことができます。
を作成する間にガイドとして組み込まれます。LScriptのコア
–65–
エンジンは、このプロトタイプを用いてD L L関数を呼び出し
typedef struct _lsfunc
ます。
{
typedef LS_VAR * (*DLLfunc)(int *count,LS_VAR
char
* (*strdup)(const char *);
*,LSFunc *);
void
* (*malloc)(int);
LScriptはそれ自体が共有ライブラリなので、LScriptをロード
void
(*free)(void *);
したホストプロセスのリソース(つまり、LightWave3D)を
void
(*info)(const char *);
活用します。 LScriptがメモリを割り当てたり、ファイルを開
void
(*error)(const char *);
く場合、LightWave3Dの利用できるリソースを使用して行い
} LSFunc;
ます。そのため、LScriptはLightWaveのハウスでは、最後に
先に定義した関数に戻ると、各共有ライブラリへの最後のパ
クリーンアップを実行してレイアウトへのメモリリークの開
始を避け、礼儀正しいゲストになろうとします。そのため、
LScriptは、終了時にスクリプトの実行時に正しく解放されな
ラメータはこのタイプの構造体、L S F u n cへのポインタです。
この構造体ポインタを使用して、内部に含まれる関数ポイン
タにアクセスできます。
かったリソースがあれば、それを解放できるように、スクリ
プトの実行により発生したメモリの割り当てすべてをトレー
LS_VAR *dllfunc(int count,LS_VAR
スします。
*parameters,LSFunc *func)
LScriptはLScriptのハウス内のゲストに礼儀正しく振る舞うこ
{
とを期待しています。最後にLScriptは、これらの重要な割り
・・・
当てを管理する際に使用する内部機能へのアクセスをゲスト
に提供します。共有ライブラリ関数がリソース(メモリある
// 5個のLA_VARからなる配列を割り当て
vars = (LS_VAR *)(*func-
いはファイル)を割り当てる必要がある場合は、これらの関
>malloc)(sizeof(LS_VAR) * 5);
数を利用することをお勧めします。しかし、これは、リソー
・・・
スをいいかげんに取り扱ってよいということではありません。
// 割り当てを解放・・・
(*func->free)(vars);
使用する資源を明示的に割り当てて解放する規制を維持すべ
・・・
きですが、標準ライブラリの代わりに、これらのエクスポー
}
トされた内部 LScript関数を用いて維持してください。そうす
れば、明示的なリソースの解放を見落とした場合にも、終了
する前にLScriptがそれを捕捉できます。
メッセージの表示
lscript.hヘッダーファイルの次のエントリはLScriptがエクス
LSFunc構造体には、LScriptの関数と名前が似ている info()
ポートした各内部リソース管理関数へのポインタを含む構造
とerror()という2つの関数ポインタがあります。これらの
体の定義です。
関数ポインタは、 LScriptの対応する関数と非常に類似してお
り、共有ライブラリを提供します。この共有ライブラリは、
情報あるいはエラーメッセージをLScriptの内部メッセージ処
理メカニズムを経由してLightWave3Dユーザに対して表示す
る手段です。
–66–
これらの関数は、構造体にリストされた他の関数ポインタと
char *getVolumeSerialNumber(void)
同じ方法で呼び出されますが、ユーザに見える形で結果を出
{
力します。
・・・
char
tmpPath[MAX_PATH + 1];
char
tmpFile[MAX_PATH + 1];
(*func->error)("severe error: bad
static
char volumeSN[50];
parameter");
BY_HANDLE_FILE_INFORMATION fileInfo;
・・・
HANDLE
hFile;
GetTempPath(MAX_PATH,tmpPath);
これらの関数に関して注意しなければならない重要なことが2
点あります。まず、LScriptに渡したメッセージは表示される
GetTempFileName (tmpPath, "LScript",
最終メッセージではないということです。LScriptはユーザに
0, tmpFile);
メッセージを表示する前に、メッセージの始め(と潜在的な
hFile = CreateFile(tmpFile,
終わり)に情報を配置します。そのため、ユーザはメッセー
GENERIC_READ |
ジの始めには大文字から始まる単語を使用しないというガイ
GENERIC_WRITE,0,NULL,OPEN_ALWAYS,
ドラインに従うべきで、ユーザに見えている情報がすべてで
FILE_ATTRIBUTE_TEMPORARY,NULL);
あると想定してはいけません。
GetFileInformationByHandle(hFile,&fil
Line #45, severe error: bad paramerter
eInfo);
第2に、 error()関数の呼び出しを行うと、共有ライブラリ
sprintf(volumeSN,"%.4X-
関数が終了するときにLScriptに現在のスクリプトの実行を停
%.4X",HIWORD(fileInfo.dwVolumeSerialN
止させるための内部フラグを設定します。そのため、
umber),
error()はスクリプト内で後に続けてエラーを発生する共有
ライブラリ関数内で重大なエラーを発見した場合にのみ使用
されることを目的としています。
LOWORD(fileInfo.dwVolumeSerialNumber)
共有ライブラリの構築
);
LScriptとリンク可能な共有ライブラリを作成する際の次のス
CloseHandle(hFile);
テップでは、D L L関数を定義(前述のガイドラインに従って
DeleteFile(tmpFile);
いることを確認)します。LightWaveWindowsのプラットフ
return(&volumeSN);
ォームでは、ローカルドライブのボリュームシリアル番号を
}
取得する方法が必要です。これはLScriptから行うことができ
ますが面倒です(しかも遅くなります)。この解決策として、
現在の状態では、 LScript内で直接この関数を使用できません
新しく「ビルトイン」関数を作成して同じタスクを行うこと
ので、LScriptのリンク条件を満たすようにこの関数を変更し
ができます。次に、Windows Win32 APIから関数を借用して
なれればなりません。しかし、変更部分は比較的マイナーな
現在のローカルドライブのボリュームシリアル番号を検索す
部分です。
るC関数を紹介します。
–67–
最初に、関数のヘッダーを" l s c r i p t . h "ヘッダーにある
に渡されたパラメータのカウントが正しいことを確認するこ
typdefと完全に一致するように変更します。すると、
とは共有ライブラリ関数の役目です。
char *getVolumeSerialNumber(void)
if(*count != 0)
{
は、次のようになります。
// 引数なし
(*func->error)("invalid parameter
LS_VAR * getVolumeSerialNumber(int
count to DLL function ... ");
*count,LS_VAR *vars,LSFunc *func)
return(NULL);
}
次に、LScriptに返す値が存在しなければなりません。元の関
数ではスタティックエリアへのポインタを返しただけでした。
これはLScriptとの対話には不十分です。 LScriptが読取り可能
なデータの1アイテムを保持する、1つあるいは複数の
ーとなります。
LS_VAR構造体を返さなければなりません。この特定関数の場
関数の本体はほとんど変更しません。ボリュームシリアル番
合は、LS_VAR構造体にラッピングされた文字列と同じ文字列
号を確認できたら、LScriptが理解できるフォーマットにパッ
を返します。
ケージングしなければなりません。元の関数では、スタティ
関数の中でプライベートな LS_VAR変数を宣言します。関数が
ック文字列エリアへの文字ポインタを返しただけでした。
返された後に、「スタティック」として宣言するために、変数
return(&volumeSN);
自体が存在することも確認しなければなりません。
しかし、LScriptが適切にデータを処理するには、 LS_VAR構
・・・
static
getVolumeSerialNumber()関数の場合は引数を取りま
せん(つまり、"void"です)。何かを渡された場合は、エラ
造体でラッピングし、LScriptエンジンにデータ型と返すデー
LS_VAR var;
タアイテム数を知らせなければなりません。関数の新しい終
・・・
了コードは次のようになります。
同様に、返す文字列は関数を返した後にも引き続き存在しな
ければなりません。
(でなければ、LScriptが「解放済み」メモ
var.type = LSSTRING;
リにアクセスする際に大問題が発生します。
)幸運にも、元の
var.data.string = volumeSN;
関数内に定義されている「永久」エリアが既にあるので、こ
こに、メモリを破壊することを恐れず文字列を置いておけま
*count = 1;
// 期待するデータアイテムの数
return(&var);
す。
}
ここで、次に getVolumeSerialNumber()関数全体を紹
・・・
static
char volumeSN[50];
介します。
・・・
次に、関数が受け付けたパラメータを変更しているので、コ
ンパイラがコンパイル時に不正なパラメータを検出すること
を期待できません。つまり、このパラメータを実行時にチェ
ックしなければなりません。LScriptから共有ライブラリ関数
–68–
LScriptへのエクスポート関数
#include <stdio.h>
#include <windows.h>
(さらに関数を追加してから)DLLを生成する準備が整ったら、
#include "lscript.h"
定義ファイルを作成しなければなりません。この定義ファイ
ルは、コンパイラが使用するプロセッサが認識できる(エク
LS_VAR * getVolumeSerialNumber(int
スポートされる)ライブラリの関数をコンパイラに指示しま
*count,LS_VAR *vars)
す。これは非常に重要なポイントです。関数が定義ファイル
{
を使用してエクスポートされていないと、LScript内の参照は
char
tmpPath[MAX_PATH + 1];
char
tmpFile[MAX_PATH + 1];
static
char volumeSN[50];
LIBRARY
static
LS_VAR var;
EXPORTS
未解決のままとなり、エラーが発生します。
BY_HANDLE_FILE_INFORMATION fileInfo;
HANDLE
test
getVolumeSerialNumber
hFile;
この定義ファイルは任意の名前を付けて保存できます。ただ
if(*count != 0)
// 引数は取りません
return(NULL);
し、D L Lライブラリをコンパイルする際にはその名前を使用
しなければなりません。この例の場合は、 "dll.def"と名
GetTempPath(MAX_PATH,tmpPath);
前を付けました。 D L Lライブラリに関数を追加する場合は、
GetTempFileName ( tmpPath, "LScript" ,
コンパイルする前に定義ファイルの"EXPORTS"セクションの
0 , tmpFile);
下に名前を追加しなければなりません。
hFile = CreateFile (tmpFile,
GENERIC_READ | GENERIC_WRITE,0, NULL,
Makefileの使用
OPEN_ALWAYS,FILE_ATTRIBUTE_TEMPORARY,
次に残っているステップの中にDLLライブラリ用のmakefileの
NULL);
作成がありますが、Makefileの作成はサイエンスというより
GetFileInformationByHandle (hFile,
もアートの世界なのでこのマニュアルの対象外です。代わり
&fileInfo);
に、この節に紹介するサンプルのD L Lソースファイルを直接
sprintf(volumeSN,"%.4X-%.4X",HIWORD
コンパイルし、他の makefilesを設計する際にテンプレートと
(fileInfo.dwVolumeSerialNumber),
して使用できる、ファンクショナルなmakefileをここに示し
LOWORD (fileInfo.
ます。このmakefileは、Microsoft Visual C++の開発システム
dwVolumeSerialNumber));
で使用するためのものです。
CloseHandle(hFile);
DeleteFile(tmpFile);
var.type = LSSTRING;
var.data.string = volumeSN;
*count = 1;
return(&var);
}
–69–
CFMACH
= -D_X86_=1
CFLAGS
= -c -W3 $(CFMACH) -DWIN32 -D_WIN32
パスが " l i b r a r y " コマンドに指定されていない場合は、
LScriptエンジンは DLLファイルを探し出すために、次の場所
をスキャンします。
/O2 /I . $(OPT)
LFLAGS
1 .現在のディレクトリ(スクリプトがある場所と同じ場合も
= -dll -def:.\dll.def
ありますがそうでない場合もあります)
OBJS = test.obj
LLIBS
2 . W i n d o w sのシステムディレクトリ(通常はW i n d o w s ¥ S y s-
= libc.lib kernel32.lib
temまたはWinNT¥System32)
.cpp.dll:
3 .このプラグインタイプ用のL S c r i p tの環境設定でのL i b r a r y-
cl $(CFLAGS) $*.cpp
Pathエントリ(ls-if、ls-orなど)
.c.dll:
cl $(CFLAGS) $*.c
all :
test.dll
test.dll:
$(OBJS)
link $(LFLAGS) -out:test.dll $(OBJS) $(LLIBS)
test.obj
: test.c
開発システムとしてMicrosoft Visual C++を実際に使用する場
合は、nmakeを呼び出すだけで、LScriptに直接リンクできる
全く新しいD L Lを生成します。他の開発システムでは、提供
されるmakefileと、おそらくその他のファイルも変更する必
要があります。
共有ライブラリの使用
LScriptを拡張する場合の、このプロセスの最後のステップは、
DLLライブラリを使用するLScriptを実際に書くことです。こ
れは、ほんの2、3行のLScriptを使用して行うことができます。
library "test.dll";
main
{
info("Your volume serial number is
",getVolumeSerialNumber());
}
–70–
LScript共有ライブラリの拡張
D L Lと他のデータポインタについて説明している付録Aの、
LSFuncのインスタンスをハウジングする新しい構造体が定義
共有ライブラリメカニズムを活用すると、ユーザ定義のオブ
ジェクトエージェントをインプリメントする際に使用できる、
されます。
共有ライブラリを作成することができます。つまり、
(技術的
typedef struct _lsdll
には、クラス定義と呼ばれている)新しいオブジェクトエー
{
ジェントを共有ライブラリの中に作成でき、これらのオブジ
const char *ClassName;
ェクトエージェント(クラス定義)のインスタンスは次の宣
const char *InstanceName;
言を使用してプログラマーがLScript内に作成できます。
use "<filename>.dll" as class <ClassName>;
LS_VAR
*instance[MAXINSTANCE];
LSFunc
*func;
} LSDLL;
独自のオブジェクトエージェントを作成するためのプロトコ
ルは、LScriptの呼び出し可能な共有ライブラリを作成するた
"ClassName"メンバーは、LScriptで設計されたオブジェクト
めのプロトコルよりはずっと複雑になります。C++クラスの設
エージェントの"クラス"名の入った文字列を指し示します。
計をエミュレートするという苦労をしておいたので、オブジ
"InstanceName"は、オブジェクトエージェントの現在の
ェクトエージェントの共有ライブラリには、データメンバや
インスタンスの入った変数名を含む文字列を指し示します。
エクスポートされたメソッドなどの、LScriptでオブジェクト
エージェントを使用できるようにする、
(デストラクタなどの)
LScriptエンジンだけからアクセスできる「メソッド」(関数)
があります。
"instance"配列は、オブジェクトエージェントのインスタ
ンスデータの MAXINSTANCE配列シリーズです。現在のイン
スタンスは、独自のインスタンスデータがあれば必ず、
instance[0]からそれにアクセスします。現在は使用され
ユーザ定義のオブジェクトエージェントを構築するための必
ていませんが、残りのエレメントはオブジェクトの継承結果
要条件を理解しやすくするため、"BobObj"という名の、役立
として必要となる可能性のある、将来のインスタンスデータ
つかどうかは疑問なオブジェクトエージェントを構築してみ
用に予約されています。インスタンスデータについてはこの
ます。"BobObj"には「パブリック」メソッドが1つだけしかな
く、そのメソッドの s t r a d d ( ) は、2つの文字列を結合し、
新しい文字列を返します。
セクションの後で説明します。
新しいプロトタイプには「パブリック」なオブジェクトエー
ジェントメソッドを作成するときに使用するように定義され
D L L関数と同様、このセクションで説明するトピックは、プ
ます。このプロトタイプはLScriptエンジンがユーザのメソッ
ログラム上の内容で、本質的に重要です。これらは本格的な
ドを呼び出す際に使用します。
デベロッパ用です。
typedef LS_VAR * (*ObjectAgentMethod)(int
*,LS_VAR *,LSDLL *);
"lscript.h"への拡張
ユーザ定義のオブジェクトエージェントを活用するには、構
造体と定数を追加して、lscript.hヘッダーファイルに組み込ま
プライベートクラスメソッド
なければなりません。
各オブジェクトエージェントの共有ライブラリは新しいオブ
ジェクトエージェントの管理機能のベースを表す4つのメソッ
ドを利用できるようにしなければなりません。これらの4つの
–71–
必須メソッドはそれぞれに異なる数のパラメータを受け取り
データメンバに適用します。"dataname"は問題のデータメ
ます。インターフェイスには4つの必須メソッドのいずれかの
ンバの名前の入った文字列です。
動作様式によって必要とされれば、さらに2つのメソッドがオ
また、インターフェイスにはさらに3種類のメソッドがありま
プションで用意されています。
す。そのうちの2種類のメソッドは、オブジェクトエージェン
4つの必須メソッドを以下に示します。
トクラスの「パブリック」データメンバへのアクセスを管理
する際に使用し、第3のメソッドは、オブジェクトエージェン
void constructor(count,variables,classinfo)
"count"は、このコンストラクタに渡されたパラメータ数を
トを(ヘッダーファイルの l s c r i p t . h の中の O A M A J O R と
OAMINOR宣言子を用いて定義された)オブジェクトエージェ
表す整数値です。
ントインターフェイスの特定バージョンにロックします。
"variable"は、コンストラクタに渡されたパラメータの値
LS_VAR *returndata(dataname,classinfo)
が入ったLS_VAR配列へのポインタです。パラメータが渡され
returndata()は、"dataname->extra"が名前をつけ
ない場合は NULL("count"は0)になります。 "class-
たオブジェクトエージェントのデータメンバに含まれる値を
info"は、クラスとインスタンス名、内で LScript関数へのポ
返します。 v o i d *は c h a r *にキャストすべきです。 o w n-
インタ、インスタンスデータへのポインタに関する情報の入
data()に前もってそのデータメンバがこのオブジェクトエ
った(前述の)LSDLL構造体のインスタンスです。
ージェントが所有するデータメンバであることを示していな
ければ、データメンバのために returndat()が呼び出され
void destructor(count,variables,classinfo)
ることはありません。
パラメータはコンストラクタのパラメータと同じですが、デ
"dataname->data.number"メンバは、参照したデータ
ストラクタは直接呼び出すことはできないので、 "count"は
メンバが配列の場合は整数をキャストしなければなりません。
必ず0、"variables"は必ずNULLです。
"dataname->data.number"はスクリプト内で使用する
インデックス値であり、ゼロを基準にしたオフセットに変換
されます。
boolean ownmethod(methodname)
このインターフェイスメソッドはオブジェクトエージェント
ご注意ください。この値はインデックス値として必要
のインスタンスが特定メソッドを持っているかどうかを調べ
な場合にのみキャストされるべきです。スクリプト処
る際にLScriptが使用します。"methodname"は、問題のメソッ
理エンジンにより明示的に設定されていないときにこの値を
ドに名前をつける文字列です。 ownmethod()は、この文字
キャストすると、特定オペレーティングシステム(有名なと
列を使用して、既知の「パブリック」メソッドと比較し、メソ
ころでは、DEC Alpha)が浮動小数点例外エラーを発生しま
ッドのいずれかとこの名前が一致している場合は trueを、指
す。
定メソッドが使用できない場合はfalseを返します。
assigndata(dataname,data,classinfo)
Boolean owndata(dataname)
LScriptは、新しいデータをデータメンバに割り当てる場合に
このプライベートメソッドは ownmethod()と似ていますが、
このオブジェクトエージェントメソッドを呼び出します。
オブジェクトエージェントが使用可能にする「パブリック」
LScriptは内部的に、既存データメンバら新しい値を割り当て
る方法があればそれを使用します。このメソッドは結果を渡
–72–
され、それに該当するデータメンバを更新するように期待さ
複数のインスタンスのハンドリング
れます。
オブジェクトエージェントの共有ライブラリに置くことので
r e t u r n d a t a ( ) の場合と同様、 " d a t a n a m e " は、
" e x t r a "エリアのデータメンバ識別子と、該当する場合は、
きる、1つのプションのプライベートメソッドは、オブジェク
トエージェントインスタンスデータの作成をハンドリングす
データメンバをインデックス処理できるのであれば、
る設計になっており、instdata()と呼ばれています。最初
"data.number"の要求したインデックスオフセットの両方
に、
「インスタンスデータ」とは何を指すか、およびなぜ必要
をハウジングする、LS_VAR構造体へのポインタです。
なのかを検討しましょう。
"data"は、新しい値の入った別のLS_VARポインタです。
「インスタンスデータ」はオブジェクトが機能するためには必
須の特定データ値のコピー、つまり、インスタンスに過ぎま
"classinfo"はLSDLLのインスタンスです。
せん。インスタンスデータの必要性に関する良い例は、ファ
version(major,minor)
イル処理のオブジェクトエージェントです。ここで示す架空
"major"と"minor"は、このオブジェクトエージェントが
のファイル処理オブジェクトエージェントには、オブジェク
機能するために必要なインターフェイスのレベルを示し、要
トエージェントデータの特定機能の一部のタイプを実行する
求したメジャーとマイナーのリビジョン値を受け取る整数の
ように定義されたメソッドがあります。インスタンスデータ
ポインタです。返された値が、プラグインでサポートしてい
をハンドリングする機能がなければ、ファイルごとに別々の
る現在のオブジェクトエージェントインターフェイスの指定
オブジェクトエージェントD L Lを維持(および宣言)しなけ
と一致していない場合は、ライブラリはロードされず、関数
ればならなくなります。その理由は、D L Lが、ファイル名や
での参照が未解決のままという結果になります。
ファイルポインタなどのアイテムを使用する際に(コンパイ
インターフェイスの特殊な動作様式は、オブジェクトエージ
ル時に宣言される)独自の変数を持っていなければなりませ
ェントクラスに「パブリック」データメンバがあるかどうかに
んが、この情報を保存できるは場所は1つしかないからです。
関係します。オブジェクトエージェントクラスに「パブリッ
1つのDLLを使用して、新しいファイルを処理する必要がある
ク」データメンバがあると、特定のオブジェクトエージェン
場合は、既存のオブジェクトエージェントを新しいファイル
トが「パブリック」データメンバを使用可能にしない(つま
の情報を用いて初期化するか、宣言されているオブジェクト
り、 o w n d a t a ( ) は無条件に f a l s e 値を返す)場合は、
エージェントの新しいインスタンスを作成するかのいずれか
returndata()とassigndata()の両メソッドはオプシ
を行わなければなりません。どちらの作業もインスタンスを
ョンとなり、インターフェイス上に存在する必要がなくなり
上書きするため、そのインスタンスに対して維持してきた前
ます。その理由としては、owndata()がtrueを返さない限
のデータを破壊することになります。(DLLのコピーは1部し
り、これらの2つのメソッドがL S c r i p tエンジンから呼び出さ
かメモリにロードされず、作成するインスタンスごとにコピ
れることはないからです。
ーを用意するのではないことを覚えておいてください。)
これらのメソッドの使用方法については、このセクションで
もう一つ別の解決策としては、個別のオブジェクトエージェ
BobObjというオブジェクトエージェントを作成するときにそ
ント共有ライブラリにインスタンスデータを個別に維持する
の例を紹介します。
独自のメカニズムを提供させることです。しかし、それには、
オブジェクトエージェント共有ライブラリのプログラマーは、
すでに確立されている標準関数を使用しないで、独自の保存
メカニズムを工夫しなければなりませんし、おそらく数が多
–73–
くなるインスタンスそれぞれを区別できるように、共有ライ
void version(int *maj,int *min)
ブラリ関数に情報を追加しなければなりません。
{
LScriptでは、オブジェクトエージェントが適切に機能するた
=*maj = 1;
めに必要なインスタンスデータを、オブジェクトエージェン
=*min = 1;
ト自体が新しくコピーできるようにinstdata()関数を採用
// バージョンの1.1が必要です
//これはインターフェイスバージョンです。プラ
グインではありません)
しています。 instdata()がある場合、 instdata() は必
}
ずオブジェクトエージェントの(インスタンスデータ値を初
B o b O b jというオブジェクトエージェントでは、ダミーの
期化するには最適な位置である)コンストラクタの前に呼び
albeitというインスタンスデータを維持するので、そのメ
出されるので、instdata()により作成するインスタンスデ
ソッドから始めます。このメソッドはオプションだというこ
ータは、作成時に入力する必要はありません。オブジェクト
とを忘れないでください。
エージェントにはinstdata()メソッドが含まれていないの
BobObjでは、 "tom"、"dick"と"harry"という名前の3
で、LScriptはオブジェクトエージェントにインスタンスデー
種類のインスタンス値を維持します。これらのインスタンス
タ が な い と 仮 定 し 、 L S D L L 構造体の特定の値(つまり、
値はすべて「パブリック」であると考えられ、ホストのLScript
instance[0])はNULLに設定されます。
からアクセスします。そのため内部的に名前を付ける必要は
オブジェクトエージェントがインスタンスデータを維持する
ありませんが、スクリプトがそれらを参照する方法を理解す
必要がある場合は、instdata()関数があり、必要な保存場
ることが必要と考えます。instdata()メソッドではインス
所を割り当てるように設計されていなければなりません。イ
タンスデータを初期化しませんので、非常に簡単になります。
ンスタンスデータの各エレメントは LS_VARデータラッパーに
保存され、LS_VARポインタとしてLScriptに返されます。複数
LS_VAR * instdata(LSFunc *func)
のエレメントがある場合は、LS_VARデータラッパーの一次配
{
列を割り当てて、処理をコンパイル後に再処理エレメントへ
LS_VAR
のポインタを LScriptに返す必要があります。 instdata()
から返される、このポインタはLSDLL構造体インスタンスの
// 3種類のデータメンバがあり、すべて「パブリッ ク」です
mydata = (LS_VAR *)(*func->malloc)(3 *
配列(instance[0])の最初のエレメントに置かれ、それ
sizeof(LS_VAR));
がオブジェクトエージェントメソッドに渡されます。
return(mydata);
これから作成するサンプルのオブジェクトエージェントでは、
*mydata;
}
インスタンスデータを維持する必要性はありませんが、例と
以下にこのメソッドに関して注意すべき重要な点を示します。
して紹介するためにインスタンスデータを維持します。
1.インスタンスデータをハウジングする際には"静的"変数を使
BobObjシェル
用しないでください。静的変数はインスタンス間で共有する、
まず、オブジェクトエージェントを version()メソッドを
単精度の値です。意図的にするとしても、各インスタンスご
提供してオブジェクトエージェントインターフェイスのバー
とにオペレーション対象となる固有のデータ値セットを持た
ジョン1.1にロックします。
せたいとは思わないでしょう。そのため、インスタンスデー
タは実行時ヒープから割り当てなければなりません。
–74–
2 .インスタンスデータは任意の方法で構成できますが、イン
void constructor(int count,LS_VAR
スタンスデータのエントリ数についてのカウントはLScriptで
*parameters,LSDLL *lsdll)
は維持しません。インスタンス配列の内容はすべてオブジェ
{
クトエージェントが認識しており、配列内のデータへのアク
LS_VAR *inst;
セスは境界を超えてはいけません。
if(count != 0)
3.LightWave3Dにメモリリークを発生させないように、必ず
LScriptが提供する資源管理関数を使用してください。LScript
// エラー!パラメータは受
// け付けません。
{
は内部メモリのすべての割り当て/解放をトレースし、LScript
標準ライブラリの malloc()を使用すると、LScriptはそれを
//(C++では、この署名と一致するクラスメソッ
// ドはありません。)
(*lsdll->func->error)(...);
理解せず、メモリを明示的に free()し忘れるとリークが発
return;
終了にメモリ割り当てが残っている場合はそれを解放します。
生します。
}
instdata()がある場合は、それはスクリプト内で新しいイ
if((inst = lsdll->instance[0]) !=
ンスタンスが作成されるときにLScriptエンジンが最初に呼び
NULL)
{
出すメソッドです。
// 確認のため...
次に完成させるメソッドはオブジェクトエージェントのコン
inst[0].data.number = 145.567;
ストラクタです。コンストラクタは必須メソッドで、スクリ
inst[1].data.string = "Dick";
プトがオブジェクトエージェントの新しいインスタンスを作
// 定数データメンバ
inst[2].data.vector[0] = 10.0;
成する際には必ず呼び出されます。コンストラクタは必ず
instdata()呼び出しの直後に呼び出されます。 instdata()がない場合は、コンストラクタが最初に呼び出されるメ
inst[2].data.vector[1] = 20.0;
inst[2].data.vector[2] = 30.0;
ソッドとなります。
}
BobObjコンストラクタで、 instdata()で作成されたイン
}
スタンスデータメンバを初期化します。コンストラクタには
スクリプトからパラメータを渡すことができ、これらのパラ
先に説明したように、オブジェクトエージェントのコンスト
メータから取り出した値を用いてインスタンスデータを初期
ラクタはLScriptでインスタンスが作成されるときに呼び出さ
化しようとするのが一般的です。BobObjというオブジェクト
れます。インスタンスはオブジェクトエージェントというク
エージェントではコンストラクタパラメータを使用しません。
ラス名を関数の呼び出しとして使用する場合に、スクリプト
プログラマーが作成します。たとえば、BobObjというオブジ
ェクトエージェントのインスタンスを作成するときは、クラ
スコンストラクタを呼び出します。
–75–
外」となるインスタンスを「クリーンアップ」する際に使用し
use "bobobj.dll" as class BobObj;
ます。このクリーンアップというのは、クリーンアップを必
・・・
要とするインスタンスデータメンバをシャットダウンし、イ
main
ンスタンスの資源(メモリ、ファイルなど)を解放すること
{
です。今回は、instdata()メソッドにより割り当てられた
・・・
bob1 = BobObj();
すべての資源もデストラクタの中で解放することにします。
//BobObjインスタンスを作成
今作成中のBobObjというオブジェクトエージェントは、複雑
・・・
でないインスタンスデータを管理するので、そのデストラク
オブジェクトエージェントコンストラクタに引数を渡さなけ
タもきわめて簡単なものです。
ればならない場合は、引数を括弧に入れます。
void destructor(int count,LS_VAR *parameters
bob1 = BobObj(1,"Hello");
,LSDLL * lsdll)
// パラメータを使用してインスタンスを作成
{
オブジェクトエージェントのコンストラクタメソッドに関し
if(lsdll->instance[0])
て注意すべき重要事項を以下に示します。
// free instdata()-割り当てリソース
(*lsdll->func->free)(lsdll-
1.コンストラクタの中で、目的のクラスのインスタンス用に
>instance[0]);
ユーザのインスタンスデータにある該当データ値を設定しま
す。これらの値は、通常このメソッドに渡されるパラメータ
}
から何らかの方法で取り出されます。たとえば、ファイル処
もちろん、各インスタンスデータエレメント内に追加リソー
理クラスのタイプであれば、オブジェクトエージェントが管
スを割り当てている場合は、各エレメントをデストラクタに
理しようとしている固有のファイル名を示すパラメータを期
トラバースし、該当するLScript関数を呼び出して、インスタ
待します。
ンスデータ配列自体を解放する前に、先にそれを解放
2.オブジェクトエージェントメソッドに提供する引数のカウ
(free()、fclose()など)します。
ントとタイプに柔軟性を持たせるだけで、オブジェクトエー
次は2つの必須オブジェクトエージェントメソッドの、 own-
ジェントメソッドを過負荷にするメソッドをシミュレーショ
m e t h o d ( )と o w n d a t a ( ) です。これら2つのメソッドは、
ンすることができます。こうすると、オブジェクトエージェ
論理値の trueまたは false を返して、オブジェクトエージ
ントがサポートする過負荷状態のオブジェクトエージェント
ェントが特定のメソッドあるいはデータメンバを扱う機能が
と一致するパターンを探すことができます。
あるかどうかを示すという点で単純です。BobObjというオブ
3.LSDLL構造体の "instanceName" 属性値は、オブジェク
ジェクトエージェントは "stradd()"という1つのパブリッ
トエージェントのコンストラクタが呼び出されるまで設定さ
クメソッドと、"tom"、"dick"、"harry"という3種類の
れません。この理由は、作成されたインスタンスはコンスト
データメンバを扱います。
ラクタが呼び出された時点ではまだ変数に割り当てられてい
ないためです。これは使用しないでください。
クラスの定義はすべてきちんと書き、デストラクタメソッド
に組み込んでください。デストラクタメソッドは「対象範囲
–76–
int ownmethod(const char *method)
て、LScriptのオペレーション内で新しくオブジェクトエージ
// 特定メソッドがありますか。
{
ジェクトメソッドを検索できない場合に何らかのエラーを生
ェントを作成できるようになります。メソッドあるいはオブ
成しないのは、これらのメソッドからマイナスの値が返され
if((method[0] == 's') &&
ると、LScriptエンジンはペアレント(あるいはスーパークラ
(strcmp(method,"stradd") == 0))
ス)に問い合わせをするからです。現在のバージョンでは、
return(TRUE);
LScriptエンジンはオブジェクトエージェント自体でのエラー
return(FALSE); //このメソッドはありません
状態を生成するだけです。
}
おそらく、サイズ的に潜在性が最も大きいのは最後の必須メ
ソッドの returndata() とassigndata() です。これら
int owndata(const char *data)
のメソッドは、オペレーティング・システムのパブリックデー
// 特定データメンバがありますか。
{
タメンバへのアクセス作業を行います。
Returndata()は要求されたオブジェクトエージェントデ
if((data[0] == 't') &&
ータメンバに入っている値を返します。このメソッドは、ア
(strcmp(data,"tom") == 0))
クセス対象のデータメンバが目的のオブジェクトエージェン
return(TRUE);
トに属していることを確認するための owndata()メソッド
else if((data[0] == 'd') &&
が最初に使用されていなければ、LScriptエンジンから呼び出
(strcmp(data,"dick") == 0))
されることはありません。しかしながら、 returndata()
return(TRUE);
は、提供されるデータメンバ識別子がそのオブジェクトエー
else if((data[0] == 'h') &&
ジェントに適していないような状況を処理するために必ず用
(strcmp(data,"harry") == 0))
意してください。戻り値がNULLの場合は、このエラー状態を
return(TRUE);
示します。
return(FALSE);
次にreturndata()のBobObjバージョンを示します。
// このデータメンバはありません}
}
これらの2つのメソッドにはエラー処理が含まれていないこと
に注意してください。メソッドあるいはデータメンバが検出
されない場合は、どちらのメソッドもエラーメッセージを全
く生成しません。これは設計上故意にそうしています。
LScriptエンジンにこの状況の取り扱いを任せます。
このインターフェイスのこれからのバージョンでは、LScript
エンジンでオブジェクトエージェントの継承をサポートでき
るようになり、この場合オブジェクトエージェントは別のオ
ブジェクトエージェントのメソッドやデータメンバを継承し
–77–
LS_VAR * returndata(LS_VAR *datamember,LSDLL
lsvar.data.vector[0] =
*lsdll)
inst[2].data.vector[0];
{
lsvar.data.vector[1] =
static LS_VAR lsvar;
inst[2].data.vector[1];
//各呼び出しに異なる値を割り当てる
static LS_VAR *inst;
lsvar.data.vector[2] =
static char
*identifier;
static int
index;
inst[2].data.vector[2];
}
else
if(!lsdll->instance[0])
{
// インスタンスデータがありません それは問題です
return(NULL);
// owndata()はあると言っていますが実際はありませ
// ん。(このようなことは発生してはならないのですが)
sprintf(errormsg,"bad datamember
inst = lsdll->instance[0];
name %s::%s.%s",lsdll->
// 読みやすくするため一部省略形を使用
identifier = (char *)datamember-
ClassName , lsdll->InstanceName,
>extra;
identifier);
index = (int)datamember->data.number;
(*lsdll->func->error)(errormsg);
if((identifier[0] == 't') &&
// スクリプトを停止
return(NULL);
(strcmp(identifier,"tom") == 0))
}
{
return(&lsvar);
lsvar.type = LSNUMBER;
lsvar.data.number =
}
inst[0].data.number;
assigndata()はreturndata()と良く似た機能を実行
}
しますが、これは値を返す代わりに、データメンバの値を更
else if((identifier[0] == 'd') &&
新します。データメンバの整合性を確認するため、更新に使
(strcmp(identifier,"dick") == 0))
用する値に対してさまざまなサニティチェックを実行します。
{
lsvar.type = LSSTRING;
lsvar.data.string =
inst[1].data.string;
}
else if((identifier[0] == 'h') &&
(strcmp(identifier,"harry") == 0))
{
lsvar.type = LSVECTOR;
–78–
void assigndata(LS_VAR *datamember,LS_VAR
else if((identifier[0] == 'd')
*value,LSDLL *lsdll)
&& (strcmp(identifier,"dick") ==
{
0))
static LS_VAR *inst;
{
static int i1,i2;
// これを「定数」データメンバとみなすため、代
// 入型はすべて不正となります。
sprintf(errormsg,
static char
static int
*identifier;
index;
"illegal assignment to
if((inst = lsdll->instance[0]) ==
NULL)
constant data member
// 省略形
return;
%s::%s.%s",
identifier = (char *)datamember-
lsdll->ClassName, lsdll-
>extra;
>InstanceName,
index = (int)datamember->data.number;
identifier);
if((identifier[0] == 't') &&
(*lsdll->func-
(strcmp(identifier,"tom") == 0))
>error)(errormsg);
}
{
if(value->type != LSINTEGER &&
else if((identifier[0] == 'h')
value->type != LSNUMBER)
&& (strcmp(identifier,"harry")
== 0))
{
{
sprintf(errormsg,
if(value->type !=
"invalid data type in
LSVECTOR &&
data member assignment
%s::%s.%s",lsdll-
value->type != LSINTEGER
>ClassName, lsdll-
&& value->type !=
>InstanceName,
LSNUMBER)
identifier);
{
(*lsdll->func-
sprintf(errormsg,
>error)(errormsg);
"invalid data type
return;
in data member
assignment
}
%s::%s.%s",
inst[0].data.number = value-
lsdll->ClassName,
>data.number;
lsdll-
}
>InstanceName,
–79–
最後に、BobObjというオブジェクトエージェントのインプリ
identifier);
メントを完了させるには、パブリックメソッド stradd()を
(*lsdll->func-
作成する必要があります。パブリックメソッドの stradd()
>error)(errormsg);
は、オブジェクトエージェントの「パブリック」メソッド用
return;
に"lscript.h"ヘッダーファイルに用意されている関数プロトタ
}
イプに付加することに注意してください。
// ベクトル以外にも整数値を使用できます
if(value->type == LSVECTOR)
LS_VAR * stradd(int *count,LS_VAR *vars,LSDLL
{
*lsdll)
inst[2].data.vector[0] = value-
{
>data.vector[0];
static
LS_VAR var;
inst[2].data.vector[1] = value-
static
char buf[512];
>data.vector[1];
static
char num[100];
inst[2].data.vector[2] = value-
static
LS_VAR *inst;
>data.vector[2];
}
if(*count != 2) // 「署名」をチェックします
return(NULL);
else
*count = 0;
inst[2].data.vector[0] =
inst[2].data.vector[1] =
// 返す値の数をエンジンに知らせる準備をします
if(vars[0].type == LSSTRING &&
inst[2].data.vector[2] = value-
vars[1].type == LSSTRING)
>data.number;
{
}
inst = lsdll->instance[0];
else
sprintf(num," (( <%g,%g,%g> ))",
{
//この値が、インスタンスのビジュアルな認証と
//して各文字列に付加されます。
inst[2].data.vector[0],
sprintf(errormsg,"bad data
member name %s::%s.%s",
inst[2].data.vector[1],
lsdll->ClassName, lsdll-
inst[2].data.vector[2]);
>InstanceName, identifier);
var.type = LSSTRING;
(*lsdll->func->error)(errormsg);
if(strlen(vars[0].data.string)
}
>= 512)
}
strncpy(buf,vars[0].data.
string,500);
else
–80–
ンスデータ(instdata())で必要となる追加の値を割り当
strcpy(buf,vars[0].data.string);
てることですが、スタティックストレージを使用して値をエ
if((strlen(buf) +
ンジンに返すメソッドをお勧めします。メモリを割り当てる
strlen(vars[1].data.string)) <
500)
のは、大切な資源とCPUの時間を消費します。
strcat(buf,vars[1].data.string);
スタティックストレージがメソッド内では実現可能なオプシ
strcat(buf,num);
ョンでなく、毎回同じアイテム数を返す場合には、メソッド
の中にスタティックポインタを割り当て、次に提供されてい
var.data.string = buf;
るLScriptのメモリ割り当て関数の malloc()を使用して、メ
*count = 1;
ソッドをはじめて呼び出すときに必要なエレメントを割り当
// 返されるエレメントが1つあることをエンジンに知らせます
return(&var);
てるという、多少エレガントな解決策があります。このよう
にすると、メモリは実際に必要になるまで割り当てられるこ
}
とはなく(スクリプト全体としてメモリが呼び出されない場
else
合もあり)
、LScriptがスクリプトを終了するときに、このよう
return(NULL);
な解放されていない資源を捕捉するので、オブジェクトエー
}
ジェントはメモリを解放する機能について関わらなくて済み
パブリックオブジェクトエージェントメソッドはモニタする
ます。
必要のあるオペレーション上のポイントがいくつかあります。
stradd(...)
1." v a r s " リスト内にあるスクリプトパラメータの数を示す
{
際に使用する、 stradd()の最初のパラメータは、値ではな
static LS_VAR *myvars = NULL;
くポインタであることに注意してください。その理由は、こ
・・・
の場所はメソッドから返されるエレメントの数をLScriptエン
if(myvars == NULL)
ジンに示すために使用されるからです。 stradd()の場合は、
myvars = (LS_VAR *)(*lsdll->func-
1エレメントだけが返されるので、エレメントを返す前にこの
>malloc)
値は1に設定されます(また、エラー時には0に初期化されま
(sizeof(LS_VAR) * 5);
す)
。
2.LScriptは値を返すために使用する「容器」が、コードの中
に手配されていることを認識しません。スタティックな値を
オブジェクトエージェントの共有ライブラリの作成
使用することにしている場合もあるでしょうし、ヒープから
オブジェクトエージェントの共有ライブラリは通常のLScript
割り当てている場合もあります。このため、LScriptエンジン
リンク可能なD L Lと同様にコンパイルできます。事実、前の
は値の処理を終了した時に、容器を捨てるという仮定はでき
節で説明したmakefileのコピーを作成し、その中に埋め込ま
ません。(つまり、ヒープから解放するか、単に無視するかで
れたファイル名を変更した後直接それを使用することができ
す。
)そのため、このメソッド(またはオブジェクトエージェ
ます。
ント)がこれらのアイテムの割り当てに全責任を持ちます。
新しいオブジェクトエージェント D L Lをコンパイルしたら、
提案したこれらの資源の作成方法は、 LS_VARのスタティッ
参照を解決しようとするときに、LScriptエンジンが調べる場
ク配列を使用するか、オブジェクトエージェントのインスタ
–81–
所の1つにそれを置かなければなりません。これらの場所につ
いては前の節で概要を説明してあります。
//bob1とbob2のデストラクタがmain()終了後に呼び出されます
}
BobObjの実験
// bob0デストラクタはスクリプトが終了次第呼び出されます。
test
BobObjというオブジェクトエージェントに関する最後の作業
{
はLScript内で実際にテストしてみることです。次に、オブジ
bob3 = BobObj();
ェクトエージェントメカニズムの機能と、BobObjからだれで
// test()にローカルなインスタンスです
info(bob3.harry);
も使用できるメソッドとデータメンバを実験できるように書
かれたLScriptを紹介します。
// bob3デストラクタはtest()が終了次第呼び出されます
use "bobobj.dll" as class BobObj;
bob0 = BobObj();
main
}
// グローバルなインスタンス
LScriptからの出力で、BobObjというオブジェクトエージェン
{
トの多くのインスタンスがすべてアライブであり、適切に機
bob1 = BobObj();
能していることを示します。
// main()に対するローカルな2つのインスタンス
bob2 = BobObj();
info(bob1);
INFO: (ObjectAgent)BobObj::bob1
// オブジェクトエ
INFO: (ObjectAgent)BobObj::bob2
ージェントインスタンスはパラメータとして
info(bob2);
INFO: HelloThere (( <10,20,30> ))
// 渡すことができ
info(bob1.stradd("Hello","There"));
INFO: I’mBob (( <10,20,30> ))
INFO: 145.567
info(bob2.stradd("I"m","Bob"));
INFO: Dick
info(bob1.tom);
INFO: <10,20,30>
ます。
info(bob1.dick);
INFO: calling test!
info(bob2.harry);
INFO: <10,20,30>
info("calling test!");
INFO: 160.567
test();
INFO: <1,2,3>
bob1.tom += 15;
INFO: <10,20,30>
info(bob1.tom);
INFO: Dick
bob2.harry /= 10;
INFO: 145.567
info(bob2.harry);
INFO: 146.567
test();
info(bob0.dick);
info(bob0.tom++);
info(bob0.tom);
// インクリメント後
–82–
プラグイン間通信
("$")で区切って指定するだけで済みます。このメカニズム
は、キューのオーナーが採用することもできますが、同じ識
LScriptには、アクティブのスクリプトからその他のLScriptイ
別子を使用する複数のスロットを含む複数のキューがある場
ンスタンスへの「メッセージ」の送信を可能にするメカニズ
合にのみ必要となります。キュー名をスロット識別子の前に
ムがあります。 このメッセージングメカニズムは「プラグイ
置いて明瞭にしなければなりません。識別子を入力しないと、
ン相互間通信(Inter Plugin Communication)」
、略してIPCと
LScriptはその識別子のある、最初のスロットを使用します。
も呼ばれています。
"MyQueue"キューのいずれかのスロットにあるデータ値にア
LScript内でIPCを採用する場合は、LScriptエンジンは使用し
クセスする必要のある別のスクリプトの中からは、次のよう
ているLScript用にメッセージ「スロット」の内部リストを作
にして簡単に、しかも迅速にそのデータ値にアクセスするこ
成します。すると、そのLScriptはこのリストの指名オーナー
となります。メッセージングエリアの作成者は「オーナー」
とができます。
になりますが、一度作成してしまうと、他のLScriptをこのリ
・・・
ストにアタッチすることができます。アクセスを調整すれば、
v1 = MyQueue$ObjectFile;
これらの「スロット」にスクリプト関連データを入力でき、
・・・
それを他のスクリプトで読み出すことができます。
IPCメカニズムは自動的に同時に複数のリクエスタからのスロ
LScriptのIPCメカニズムを使用するには、「キュー」と呼ばれ
ット値へのアクセスが発生しないようにします。2つスクリプ
る保持エリアを指定します。この保持エリアには任意の数の
トが同じ( CPU)タイムにスロットにアクセスしようとする
確認済みスロットが存在します。作成したいキューごとに、
と、最初のリクエスタがそのスロットを読取り/更新し、スロ
exposeコマンドを使用して宣言します。
ットをロックするまで片方のリクエスタは待機しなければな
expose <slot identifier(s)> as <queue
りません。
identifier>;
キュー/スロットの組み合わせが存在しない場合、あるいは
データを入力して初期化していない場合は、すべての読取り
expose対象のスロット識別子はキューのデータ保存エリア
を示す間接的なポインタになります。キューが作成されると、
アクセスから返される値は必ずnilになります。
そのキューのオーナーは、スクリプトの範囲内にある宣言済
配列キューのメンバー
みのグローバル変数と同様に、これらのスロット値にアクセ
IPCキューメンバーも配列として宣言され、ループのIPCキュ
スし、変更することができます。
ーデータをシーケンシャルにアクセスし、更新ができます。
キュー配列は他の LScript配列と同様に宣言され、参照されま
expose MakeObject, ObjectFile as MyQueue;
す。
・・・
expose objects[100] as MyQueue;
ObjectFile = nil; // キュースロット
if(MakeObject != nil)
・・・
{
通常のキュー変数の場合と同様に、ローカル変数を扱うよう
・・・
にスクリプト内の配列エレメントにアクセスします。
IPキュースロットにアクセスする必要がある他のLScriptイン
スタンスは、キュー名とそのキュー内のスロットをドル記号
–83–
@warnings
・・・
for(x = 1;x <= 100;x++)
// この"expose"コマンドは1スロットの"position"を用いて
objects[x] = <0,0,0>;
// 「マスター」と呼ばれるIPCキューを作成します。
expose position as Master;
キュー配列構造に、プリプロセッサマクロを活用することも
create
できます。
{
@insert "lights.inc"
setdesc("Channel-lock Demo - Master
・・・
Object");
// 'TOTALLIGHTS' defined as 75 in"lights.inc"
}
process: ma, frame, time
expose light[TOTALLIGHTS] as LightQueue;
{
・・・
position = ma.get(POSITION,time);
for(x = 1;x <= TOTALLIGHTS;x++)
//冗長になっても良ければ、あるいは特定キュースロットを
light[x] = <0,0,0>;
//識別する必要があれば、代入で明示的にキューを識別す
//ることができます。
Master$positon = ma.get(POSITION,
各キューエレメントは必然的にキュースロットエントリとな
り、単一プロセスで作成できるスロットエントリ数には実際
time);
的な限度があることに注意してください。この限度はスクリ
}
プトを実行するオペレーティングシステムが決定します。キ
ュー配列の使用はなるべく控えてください。
ここに、Masterキューを問い合わせて、マスタースクリプト
この節では、LS/IA(アイテムアニメーション)スクリプト処
の位置を取得し、Xモーションチャネルをプライマリオブジェ
理プラグインと一緒に使用するように設計されている2つの
クトのXモーションチャネルと一致させる「スレーブ」スクリプ
L S c r i p tについて簡単に説明します。これらのスクリプトは、
トがあります。
2つのオブジェク間の「マスター/スレーブ」関係をセットアッ
プします。この場合、「マスター」であるオブジェクトは
LScript IPCメカニズムを用いて「スレーブ」オブジェクトに 3
次元での位置をブロードキャストします。処理の間、スレー
ブオブジェクトのスクリプトは、マスターがポスティングす
るメッセージを待ちます。メッセージがポスティングされる
と、スレーブはマスターのX軸位置とスレーブのX軸位置を一
致させ、そのチャネルにスレーブオブジェクトを効果的にロ
ックします。
「マスター」スクリプトはIPCキューを作成し、スレーブオブ
ジェクトがアクセスし、処理できるように、ここにフレーム
単位で位置をポスティングします。
–84–
適格データタイプ
@warnings
スクリプト間でデータを通信する場合の、 IPCキューメカニズ
create
ムを使用した転送に適するデータタイプは次のとおりです。
{
setdesc("Channel-lock Demo - X-Axis
string (up to 255 characters)
Slave");
number
}
vector
process: ma, frame, time
'nil'
{
メカニズムが進化するにつれ、さらに複雑なデータタイプが
pos = ma.get(POSITION,time);
IPC転送に適するようになるでしょう。
newpos = Master$position;
// マスターのキューへのアクセス
if(newpos == nil)
// 障害がある場合は、グレースフルに復元してください
ma.set(POSITION,pos);
else
ma.set(POSITION, <newpos.x, pos.y,
pos.z>);
}
これらの2つのスクリプトがレイアウト内のオブジェクトに付
加されている場合は、1つのオブジェクト(「マスター」)だけ
がキーフレーム付きアニメーションを必要とします。
「スレー
ブ」オブジェクトは、X軸に沿って自動的に移動し、フレーム
単位にスレーブの位置をマスターの位置と合わせます。この
エフェクトを達成するためにレイアウトにすべてを読み込む
順序は次のとおりです。
1.「マスター」オブジェクトを読み込む
2.「マスター」LScriptをオブジェクトと関連付け、起動する
3.「スレーブ」オブジェクトの読み込む(「スレーブ」オブジ
ェクトが「マスター」オブジェクトの後に現れるように読み
込む)
4.「スレーブ」 LScriptをそのオブジェクトと関連付け、起動
する
–85–
Macintoshに関するLScriptの注意事項
LScriptプリプロセッサ
LScriptのPowerMacポートは、他のLightWave3Dプラットフ
プリプロセッサとは?
ォームで使用できるすべての機能を提供、あるいはエミュレ
名前が示すとおり、プリプロセッサは入力を別のプロセスに
ートするように設計されています。3つの顕著な例外を除き、
渡す前に処理を行い、一部を潜在的に変更するものです。こ
この目標は達成されました。他のLightWave3Dプラットフォ
の点では、プリプロセッサは入力が通過するフィルタです。
ームで作成された、あるいはコンパイルされたスクリプトは
LScriptにプリプロセッサを使用するよう指示する方法
P o w e r M a cのプラットフォームで変更することなく実行でき
指示は必要ありません。
ます。
実行を選択した LScriptは、プリプロセッサ特有の命令あるい
LScriptのPowerMacポートに関して注意しなければならない
は指示が含まれているかいないかにかかわらず、自動的にプ
例外は system()、systemex()、matchfile() の3つ
リプロセッサを通過し、フィルタ処理されます。プリプロセ
のコマンドです。これらのコマンドはPowerMacのLScriptに
ッサは実行スクリプトのコンパイルプロセスの一部にすぎま
組み込むことができますが、その動作は変更されています。
せん。
この変更が発生する理由は、オペレーティングシステム固有
LScriptプリプロセッサ
のコマンドインタープリタ(a.k.a., シェルプロセス)が存在
L S c r i p tプリプロセッサメカニズムは L S c r i p t作成者に対し、
しないことです。オペレーティングシステム固有のコマンド
インタープリタが存在すれば、これらのコマンドが必要とす
(技術的には、プリプロセッサパーランスで「マニフェスト定
数」として参照される)
Compiler Directives 、
Insert Files、Preprocessor Macrosの3つの主要
る機能を提供できます。
s y s t e m ( ) および s y s t e m e x ( )コマンドは共にL S c r i p tの
P o w e r M a cバージョンで n i lを返し、提供されるパラメータ
機能を提供します。
すべてを全く無視します。これはシェルプロセスをMacOSが
LScript内のプリプロセッサディレクティブはすべて、アット
固有に認識できないからです。
マーク("@")から始まり、次にディレクティブ名が続きます。
次に例を示します。
matchfiles()コマンドは機能しますが、ファイルパター
ンパラメータを無視します。これも、MacOS下ではこの機能
に合ったパターンを提供するコマンドインタープリタが存在
// オブジェクトを回転させる単純なスクリプト
@warnings
しないためです。P o w e r M a cでは、このコマンドは指定パタ
・・・
ーンを無視して、指定ディレクトリにあるすべてのファイル
LScriptの旧バージョンでは、 #pragmaキーワードを採用し
を返します。
てこの機能の一部を提供していましたが、これは現在も
制限値を超えると、L S c r i p tのP o w e r M a cバージョンはL i g h t-
LScriptファイルに表示できます。しかし、それは旧式となっ
Wave3Dプラットフォームの機能と全く同様に動作します。
たため、将来的にはLScriptエンジンから外すことになります
ので、これを使用することはお勧めできません。
コンパイラディレクティブ
コンパイラディレクティブは、コンパイラあるいはインター
プリタに対して動作を変更する、あるいは影響するような命
令を指します。L S c r i p tでは、コンパイラディレクティブが
–86–
LScriptの中に現れる場合に限りコンパイラディレクティブを
になると、クリーンアップ手段となります。これはコンパイ
適用します。
ル済みスクリプトや"lax"宣言ではサポートされません。
LScriptのプリプロセッサが認識できるコンパイラディレクテ
version {major.minor | "major.minor"}
ィブは次のとおりです。
LScriptエンジンではスクリプトに対して、そのスクリプトを
warnings [count]
実行いる際に使用するLScriptプラグインの最小バージョンを
指定できます。プラグインの以前のバージョンではコンパイ
warningsというディレクティブは、LScriptに実行時警告メ
ッセージの表示をしないように命令します。オプションの
ルエラーを発生する、新しい機能を利用したスクリプトには
[count]パラメータは表示される最大警告数を示します。
有効です。
警告メッセージは、スクリプト実行中にLScriptエンジンがデ
バージョンインジケータは、文字どおりの不動小数点値にも、
ータの損失、異常実行環境を検出した場合に生成されます。
あるいは文字列値にもできます。インタープリタはピリオド
たとえば、返し引数のカウント以下の配列へのユーザ定義手
(".")で区切ったメジャー値とマイナー値だけを有効とみな
順の返し値を割り当てると、それはLScriptの実行中に必ず警
します。
告メッセージを生成することを保証することになります。
Autoerror
警告はコンパイル済みスクリプトでは自動的にオフに設定さ
ト、あるいはモデラー特有のコマンドと関数の戻り値をスク
れます。
リプトに提供します。これにより、スクリプトはコマンドが
errors count errorsというディレクティブは、表示さ
れる最大実行時エラー数をLScriptに提供します。 countパラ
とができます。しかし、スクリプトプログラマーが、これら
メータは整数値で、必須です。エラーメッセージはオフには
の潜在的なエラー条件を管理するために必要なコードを追加
LScriptエンジンは通常、すべてのレイアウ
失敗したかどうかを判断でき、適当と思われる処置を行うこ
できませんし、 countパラメータをゼロ (0)に設定すること
したくない状況も考えられます。このような場合には、スク
もできません。
リプトプログラマーは autoerrorディレクティブを指定で
エラーメッセージはコンパイル済みスクリプトではイネーブ
きます。このディレクティブはユーザに対してエラーメッセ
ルになっています。
ージを発行して、エラー状態を自動的に処理し、スクリプト
を終了するようにLScriptに命令します。
unusedスクリプトの開発途中、ご使用のスクリプトと未使
asyncspawn
用の変数とが混ざってしまう可能性があります。大きなスク
LScriptには、スクリプトの実行中に外部プロセスを起動させ
リプトでは、これらの「死んだ」変数を探し出し、パージす
るには膨大な時間がかかります。
る機能があります(この機能の図についてはb a t c h . l sという
unusedディレクティブは LScriptに一度も使用されていない、
LScript例を参照してください)。LScriptエンジンのデフォル
宣言されている変数(つまり、割り当てた値を)を検出して
トの動作は、これらのプロセスを同時に実行すること(つま
レポートさせます。スクリプトが実行を終了すると、LScript
り、外部プロセスが完了するまでLScriptの実行を停止するこ
は未使用と判定した変数毎にダイアログウィンドウを表示し
と)です。しかし、スクリプトプログラマーが外部プロセス
ます。
と対話したい場合もあります。この場合、スクリプトプログ
ラマーは、LScriptに外部プロセスを非同期に実行するように
このディレクティブは strictディレクトリが有効な場合のサポ
指示し、それらを LScriptと平行して操作しなければなりませ
ート機能として備えられており、スクリプト開発が完成間近
–87–
ん。asyncspawnディレクティブはこのような状況で使用し
様式か、またはvarステートメントで大きさを決定する必要が
ます。
あるような動作様式に変更します。
nonrandom
n o n r a n d o mディレクティブは、 l i n e (
) ファイルオブジェクトエージェントメソッドを使用して、
現在の宣言モードに関わりなく、多次元配列は必ず明示的に
LScriptがスクリプトプログラマーに提供可能なASCIIテキスト
Insert Files
ファイルラインへのランダムアクセスを使用不可にします。
ファイルは、LScriptエンジンがコンパイルするときにLScript
これを指定すると、LScriptはラインオフセットを決定するた
に「挿入」できます。オリジナルのスクリプトの一部と同様に、
めのテキストファイル( ASCIIモードで開いたファイル)のプ
これらの挿入ファイルはエンジンを調べます。
(事実、プリプ
宣言しなければなりません。
リプロセスを実行しません。 pragmaを採用したスクリプト
ロセッサは実際に最終スクリプトをエンジンに渡す前に、オ
でline()メソッドにアクセスしようとすると、実行時エラ
リジナルのスクリプトの一部とします。
)
ーとなります。
標準LScriptはプリプロセッサコマンドなどをハウスできます。
スクリプトがラインにランダムにアクセスする必要なく、大
Insert filesは、複数のLScriptに対して利用可能としたい共通
きなテキストファイルを処理するような場合は、このディレ
コマンドとコードをハウジングする際に使用します。こうす
クティブを活用すると、スクリプト全体の実行速度を目にみ
ると、その挿入ファイルを共有するL S c r i p tすべてにおいて、
えて向上させられます。
スクリプトコードが重複することを防ぐことができますが、
literalpaths
類似性が大幅に少なくなり、それをコピーする際にデータの
L S c r i p tは(現在のところ)3つの非常に異なるオペレーティ
機能や意味を変えてしまいます。挿入ファイルにハウジング
ングシステム上で動作するため、
した共通コードも、1つの場所のすべてのスクリプトに関して
matchfiles()、getfile()などの関数に提供するファ
更新を一度実行するだけですべての従属スクリプトを更新で
イルパスを現在のオペレーティングシステムにより適したも
きるという利点があります。
のにしようとします。たとえば、Macintosh OSでは、UNIXの
挿入するファイルの名前を指定する、文字列リテラルを後に
フォワードスラッシュ ( / ) とM S - D O Sのバックスラッシュ
(\)は、Macではディレクトリの区切りに標準的に使用され
ているコロン(:)に変換されます。
続けた、 insert ディレクティブを使用して、元のスクリプ
ト(と、別の挿入ファイルに、30レベルの深さまで)にファ
イルを挿入できます。
literalpathsというディレクティブは、この内部処理を
・・・
使用不可にし、LScriptエンジンにスクリプト内に現れるファ
@insert "myinc.lsi"
イルパスを使用させます。
strict
・・・
LScriptでは、前の"var"ステートメントで
明示的に宣言せずに(また配列の場合は、上限を明示的に宣
挿入ファイルに絶対パスがない場合、LScriptプリプロセッサ
言する必要なく)必要な場合はいつでも、変数と配列を使用
は次の手順でそのスクリプトを検索しようとします。
できます。しかし、すべての変数と配列を明示的に宣言する
1.現ディレクトリ(実行中のスクリプトと同じロケーション
ことを必要にして、スクリプトの開発時にさらに構造体を追
の場合もあればそうでない場合もある)を調査
加したい場合も生じます。 strict というディレクティブは
2.LibPathの構成要素が指定したディレクトリを調査
LScriptエンジンを変数と配列を明示的に宣言するような動作
–88–
挿入ファイルを検索できない場合は、LScriptプリプロセッサ
そのため、TOTAL_LIGHTSの定義の後に次のスクリプトコー
はエラーメッセージを提示して停止し、LScriptエンジンは終
ドが処理された場合は、
了します。
・・・
プロセッサディレクティブは各挿入ファイルを処理するごと
for(x = 0;x < TOTAL_LIGHTS;x++)
に継続して、評価され、蓄積されます。
・・・
LScriptプリプロセッサはインクルードファイルに対して名前
LScriptエンジンは実際には次のように解釈します。
の付け方を一致させるように要求しません。名前が正確に
insertディレクティブに提供されれば、任意の名前を付けられ
・・・
ます。
for(x = 0;x < 100;x++)
・・・
Preprocessor Macros
Preprocessor Macros(あるいは、ハードコアソフトウェアデ
マクロの置換は他の処理を実行する前にプリプロセッサ内で
ベロッパの場合はマニフェスト定数)は、エイリアスに非常
発生します。
に類似した動作をします。スクリプトコード内でプリプロセ
ッサがマクロ識別子と遭遇した場合は、マクロ識別子の値を
High Visibility
識別子自体に代入します。これにより、(スクリプト内の数多
LScriptプリプロセッサのマクロにはHigh Visibility(高可視性)
くの場所の値自体を変更するのではなく)ローカライズの際
と呼ばれる機能があります。つまり、識別子を検索している
のコード変更が簡単になり、スクリプトコードを読みやすく
間は、プリプロセッサは識別子の文脈には関与しないという
します。(つまり、"SELECT_SPHERE"のほうが"566"よりもず
ことです。識別子が開始と終了の2つの引用符 ("")の間に現
っとわかりやすいということです。
)
れない限り、プリプロセッサは置換を実行します。これは、
マクロは、埋め込むことができます。つまり、マクロ識別子
従来のプリプロセッサで置換を実行する前は、識別子をスタ
が別のマクロ識別子値の中に現れた場合は、メイン識別子を
ンドアロンの文脈にしておかなければならないのとは対照的
スクリプトコードに代える前に、埋め込み識別子に対する置
です。一般に、識別子の周りに句読点と空白スペースがある
換が発生します。
と、従来のプリプロセッサがそれをスタンドアロンの文脈と
プリプロセッサマクロはd e f i n eディレクティブを使用して定
理解するには十分です。
義され、マクロ識別子名とその識別子に代入される値が後に
この例を見てみましょう。次のコード行が従来のプリプロセ
続きます。
ッサ(たとえば、Cプリプロセッサ)に渡されると、スタンド
アロンと理解することが可能な、文脈内に埋め込み識別子が
・・・
ないので(つまり、それは別の識別子の一部なので、読めな
@define TOTAL_LIGHTS 100
いため)
、コンパイル時エラーが発生します。
・・・
#define ONEFIFTY
上の例では、識別子"TOTAL_LIGHTS"には100という値が代入
15
・・・
されます。この識別子がスクリプトコード内(あるいは、定
x = ONEFIFTY0;
義後に挿入されたファイルで検出したコード内)のどこかで
発生した場合、 LScriptプリプロセッサは、コンパイル対象の
LScriptエンジンに渡す前に、出力コード内の値を代入します。
–89–
// <--- エラー! 識別子
// "ONEFIFTY0"はありません
Ver.2.0での変更点
しかし、LScriptのプリプロセッサはこの状況に対して異なる
処理を行います。
@define ONEFIFTY
このドキュメントはLScript v2.0の公式ベータ版に対するリリ
ースノートです。
15
ここに記されている版毎の変更点は言語に対してのみの変更
・・・
x = ONEFIFTY0;
点となります。
// <--- 値15をxに代入
スクリプトシステムにはLightWave v6.0 プラグインAPIに伴
非常にわかりやすいこのメソッドは、強力ですが、埋め込み
う変更がまだ完全には統合されてはいません。
マクロ名を含むスクリプト変数あるいは関数識別子を偶然に
使用した場合は多くの問題が発生します。LScriptをコーディ
ングするときはこのことを念頭においておいてください。
•関数filefind()が新規追加されました。
まとめ
この関数はファイル名(パス情報を除く)を指定すると、ファイ
最後に、十分に機能し、LScriptプリプロセッサの能力を示す
ル位置を特定するためアプリケーション内のディレクトリの
ことができる、やや歪んだ例を示します。
パスをスキャンします。
関数からはファイルへのパスが返されます。
@define SELECT 15
@define SELECT2 string("SELECT ",SELECT0)
if((where = filefind(“lw.cfg”)) != nil)
@define SELECT3 "Bob!"
{
@define VERSION_DIRECTIVE version 1.0
...
@define BEGIN_BOBS_MAIN main {
ファイルを検索するためにこの関数では関数 getdir()で指
@define END_BOBS_MAIN }
定するパスを使用します。
@define REM //
@insert "includes.h"
•関数filecrc()が新規追加されました。
@VERSION_DIRECTIVE
この関数はファイルコンテンツのCRC-32値を計算し、整数値
@warnings
を返します。
BEGIN_BOBS_MAIN
•LScriptは連想配列として知られている配列タイプを新規追加
info(SELECT2);
しました。
REM prints "SELECT 150"
連想配列とは整数インデックスの代わりに文字列値を使用し
info(SELECT2 + SELECT3);
てインデックスをつける配列のことです。連想配列はCやPas-
REM using string math, prints "SELECT
calでみられるようなユーザー定義の構造体をシミュレートす
150Bob!"
るために使われる強力なメカニズムです。
連想配列においては、使用されるインデックス値(キャラクタ
END_BOBS_MAIN
文字列)は属性を連想させるようなシンボルとなっており、ま
たシンボルを用いてインデックスがつけられている配列の中
に属性が含まれることになります。
混乱してしまいそうですが、実際には非常に明瞭です。
–90–
新しいインライン条件を使用して単一文で条件評価できるよ
fruit_color[“apple”]
= “red”;
fruit_color[“banana”]
...
= “yellow”;
fruit_shape[“apple”]
= “round”;
...
fruit_shape[“banana”]
...
= “curved”;
error(“Division by zero!”) when z == 0;
...
うになりました。
x = 1 if y == 15 && cos(4.35);
fruit_weight[“apple”]
= 128;
// グラム
x = 1 unless y == 10 || z == 2;
fruit_weight[“banana”]
...
= 117.3;
// グラム
...
break if x == 5;
...
この簡単な例をみてもわかるとおり、構造体のインスタンス
return 5 if !upper_limit;
の名称がインデックスシンボル(例:”apple”や”banana”)
...
となっています。
各構造体のメンバはそれぞれ実際の各配列の名称となります
•最終式の評価結果を保持する暗黙の'this'コンテナが新規追加
(例:”fruit_color”や”fruit_shape”)。
されました。
連想配列は新規追加された連想初期化演算子'$'を使用して作
このシステムはまだ完全には実現していませんが、中間値を
成/初期化が可能です。この新しい演算子は初期化ブロック演
使用して即値をハンドルする必要がなくなります。
算子('@')と同様の形式で使用されます。
...
normal_array = @1,2,3,4@;
while(!file.eof())
assoc_array
{
= $ .. $;
file.read();
ただし連想配列を初期化するためには、一組のエレメントを
使用しなければなりません。組となる各エレメントの後者に
// 行はC++コメントに続いて
// “PUB”で始まりますか?
if(s~^PUB.*\/\/.*~)
はデータを、前者には後者のデータに対する連想シンボルと
なるキャラクタ文字列を指定します。
fruit_color
// 行が’this’に入ります
info();
= $ “banana”, “yellow”,
}
“apple”, “red” $;
...
•新しい形式の条件式が利用可能となりました。
従来の条件式では前提条件位置においてif()テスト構造を用い
ています。
if(<expression>)
{
...
}
–91–
// ユーザーに表示...
•ブーリアンは”short circuited”(短絡回路)となり、以下のよ
•LScriptに正規表現と検索置換用のイン言語がサポートされま
うな式が使用できるようになりました。
した。
正規表現とは独自の特定メタ文字言語を持つ強力なパターン
...
一致関数です。
file = “C:\\CONFIG.SYS”;
パターン一致システムは UNIX上で編成されたもので、ソフト
f = File(file,”r”) || error(“Cannot open
file '“,file,”’”);
...
ウェアの世界で広く普及してきました。正規表現で利用可能
なリファレンスはとても巨大なものとなるため、ここでは詳
細については説明しません。
•LScriptのジェネリックシステムはレイアウトの新しい
それよりも、どのようにLScript内で使用するのかを説明しま
CommandSequenceシステムをサポートするようになりまし
す。
た。
L S c r i p tで正規表現を使用してパターン一致を実行するには、
現在これを容易にするための1 6 0を超える新規コマンドが用
新規"s~~"演算子を使用します。この演算子は提供された正
意されています。 C Sコマンドは名称によってアクセスされ、
関数としてLScript内に存在しています。
規表現を用いて、キャラクタ文字列を比較しパターンが存在
するか確認するよう LScriptに命令します。
@version 2.0
// 文字列は大文字”B”で始まっているか、
generic
// その後ろの文字列内のどこかに
{
// “o”が連続して2つ入っているかを調べます
if(“Bob Hood” == s~^B.*oo~)
{
AddNull();
}
...
CSコマンドがパラメータを要求する場合には、UDFを呼び出
また正規表現はキャラクタ文字列において検索置換を実行す
してパラメータを提供します。
•LScriptのプリプロセッサは新規プラグマ指示語”script”をサ
ポートすることになりました。
るのにも使用されます。このメカニズムには "r~~~" 演算子
を使用してアクセスします。
この演算子は指定したパターンに一致する文字列を検索し、
この指示語はLightWaveのLCoreシステムがプラグインとして
一致すれば指定した文字(列)で置換するようLScriptに命令し
追加されたスクリプトを識別可能にするための識別子です。
ます。
@script modeler
検索置換メカニズムにアクセスするには、新規の検索置換代
@script displace
入演算子"~="を使用します。
@script generic
@script motion
@script image
@script replace
@script master
@script shader}
–92–
// s/r 演算子を使用した検索置換
// s/r演算子を使用した検索置換
if((input = File(“nfa.c”,”r”)) == nil)
return;
if((input = File(“nfa.c”,”r”)) == nil)
return;
if((output = File(“nfa.bak”,”w”)) == nil)
return;
if((output = File(“nfa.bak”,”w”)) == nil)
return;
while(!input.eof())
sr = r~^PRIVATE~static ~;
{
while(!input.eof())
line = input.read();
{
//行の始端(^)において発見された文字列"PRIVATE"は
line = input.read();
// 文字列"static"に置き換えます
line ~= sr;
output.writeln(line);
line ~= r~^PRIVATE~static ~;
}
output.writeln(line);
input.close();
}
output.close();
input.close();
またLScriptは新規関数 regexp()を使用してキャラクタ文字
output.close();
列から正規表現を構成することもできます。この関数により
正規表現パターンは変数への代入も可能なので、代わりに変
使用する正規表現パターンをユーザーが入力することが可能
数を使用することもできます。
となるのでとても便利です。
// 文字”PUB”で始まるファイル内の行を表示します。
// 使用する正規表現をコンパイルします
expr = regexp(“^PUB”);
// コンパイルに失敗すればregexp()からは’nil’が返ります
if(expr == nil)
return;
if((file = File(“nfa.c”,”r”)) == nil)
return;
while(!file.eof())
{
line = file.read();
if(line == expr)
info(line);
}
–93–
さらに正規表現は'this'コンテナも認識します。
a[1] -> nil
...
a[2] -> nil
while(!file.eof())
a[3] -> [1] -> nil
[2] -> nil
{
[3] -> nil
file.read();
[4] -> nil
if(expr)
[5] -> [1] -> nil
info();
[2] -> 0
}
多次元配列はリニア配列をつなげて構成することもできます。
...
a[5] = “Bob”;
b[3] = a;
•LScript内にはもうエンティティとしての多次元配列は存在し
ません。
b[3,5,2] = 'a’;
厳密にいえば配列は全てリニアとなります。しかし他の配列の
// 文字列”Bob”が”Bab”となります
エレメントとして配列を割り当てることは可能なので、スクリ
配列は他配列のメンバとなる事が可能なので、エレメントと
プトにより実行時に多次元配列を構成することができます。
しての配列はユーザー定義関数へ渡すことも可能となります。
このようなユーザー定義の多次元配列はリニアな配列と同様
に動的でどのポイントにも自由にエレメントを追加するでき
ます。
// 多次元配列を生成します
a[3,5,2] = 0;
効率上、この形式で作成する多次元配列はしっかりとしたも
のではありません。
例えば上記の配列は3個のエレメントを持つ配列を生成します。
この配列の3番目のエレメントは5個のエレメントを持つ配列
でありその配列の5番目のエレメントは2個のエレメントを持
つ配列でありその配列の2番目のエレメントに0を代入してい
ます。
–94–
この形式で参照されるイメージはスクリプトがランタイム実
...
行用にコンパイルされている場合には無視されます。
// 関数へ渡すサブ配列
コンパイル済みのスクリプトが実行される時点で、参照され
るイメージがレイアウトから利用可能な状態でなければなら
a[5] = “Bob”;
b[2] = 99.9;
ないからです。
b[3] = a;
•関数ctlimage()はイメージを縮小して表示する場合に使用する
c[8] = b;
パラメータ(オプション)を新しく3つ追加しました。
5番目のパラメーター(オプションである透明度ベクトルの後)
info(c);
は縮小ファクターまたはイメージの幅のサイズを指定します。
info(c[8]);
6番目のパラメーターは縮小ファクターもしくはイメージの高
info(c[8,3]);
さのサイズを指定します。最後の7番目のパラメーターはブー
info(c[8,3,5]);
リアンフラグでイメージのアスペクト比を保存するかどうか
をLScriptに指示します。
test(c);
デフォルトではアスペクト比は保存されません。
test(c[8]);
縮小用に提供される幅と高さをあらわす数値はタイプにより
test(c[8,3]);
LScriptで解釈されます。どちらか一方のコンポーネントに対
し整数で値を提供すると、値は結果イメージの絶対幅(ピクセ
test(c[8,3,5]);
ル単位)であると解釈します。
}
一方で浮動小数点数値を渡せばLScriptはパーセンテージファ
test: a
クター(1.0は 100%)であると解釈し、オリジナルのイメージ
{
幅もしくはイメージ高さに対しこの値を適用し最終ピクセル
info(a);
の幅(高さ)を決定します。
}
このメカニズムはイメージを拡大するために設計されてはい
ないので、イメージの元の大きさを超えてしまうような結果
•(Image Editorを通して)レイアウトに読み込まれたイメージを
を引き起こす値を指定しても元イメージの大きさとなります。
関数ctlimage()を使用して表示できるようになりました。
イメージ名称の前にドル記号文字($)をつけることでディスク
上のイメージファイルを探しにいく代わりに、読み込まれて
いる任意のイメージファイルを使用するようになります。
ドル記号文字で始まる名称はレイアウトでイメージに対し表
示される名称文字列と正確に一致している必要があります。
...
ctlimage(“$ph_019.tga”,0,0);
...
–95–
...
@warnings
// (0,0)の位置にオリジナルの40%の幅
// 30%の高さでイメージを表示します
ctlimage(“$ph_019.tga”,0,0,,.4,.3);
...
output;
count;
main
{
// (0,0)の位置に幅100ピクセル、高さ100ピクセルで表示し
// アスペクト比を保存します
// (表示時には正確には100×100ではなくなるということです)
ctlimage(“$ph_019.tga”,0,0,,100,100);
...
count = 0;
chdir(“\\”);
// ルートディレクトリから開始します
do_dir();
info(count,” directories
processed!”);
// (0,0)の位置にオリジナルの形式(修正なし)で表示します
ctlimage(“$ph_019.tga”,0,0);
}
// “depth-first(縦型)” 再帰ディレクトリ走査
do_dir
•ユーザー定義関数が再帰的に呼び出せるようになりました。
この機能はユーザー自身がスクリプト内で定義している関数
{
に関してのみ拡張が可能です。定義済み関数 ( L S c r i p tでは
if((directories = matchdirs(“.”,”
*.*”)) == nil)
return;
main()やoptions()関数など)は再帰的に呼び出すことは
できません。
再帰は強力な機能ではありますが、同時に注意が必要で危険
len = directories.size();
なものです。何をしているのか理解していないと、無限ルー
for(x = 1;x <= len;x++)
プにはまってしまいます (アプリケーションが落ちる原因とも
{
なります)。LScriptは再帰に関してレベルの制限はありません
が、実質的な深さに制限(メモリなど)の限界があります。
chdir(directories[x]);
再帰を使用する前に、何をするのかをよく確かめてください。
++count;
do_dir();
以下に示す例は、再帰を用いてディレクトリ構造全体を走査
// <-- 再帰
chdir(“..”);
しドライブ上に存在するディレクトリ数をカウントするモデ
}
ラーのLScriptです。
}
•LScript言語に反復構造foreach()が新規追加されました。
これは一連のリニアな値を通しての反復処理を簡易化するよ
う構成されています。各値を保持するために使用される変数
や反復が可能なデータタイプへと変換するための式を引数と
して取得します。反復 foreach()は反復用に以下のデータ
タイプを受け付けます:
–96–
整数、数値、ファイルオブジェクトエージェント、配列(モデ
•LScriptがインターフェイスを提供するレイアウトオブジェク
ラーLScriptの自動配列 point[]とpolygons[]も含む)、そしてレ
トのリストにイメージオブジェクトエージェントが追加されま
イアウトLScriptのレイアウトオブジェクトエージェントです。
した。
getfirstitem()はIMAGEもしくは "IMAGE"を受け付け
...
るようになり、レイアウトのイメージリストにおける最初の
editbegin();
イメージファイルを返します。
foreach(x,polygons)
読み込まれていない場合には'nil'を返します。
info(x);
各イメージオブジェクトエージェントには以下の属性があり
editend();
ます:
...
-------------------...
foreach(x,10 - 5)
name
インターフェイス上に表示される名称
isColor
width
height
カラーイメージがモノクロかを示すブーリアン
イメージの幅(ピクセル単位)
イメージの高さ(ピクセル単位)
info(x);
...
さらに各イメージオブジェクトエージェントは以下のメソッ
--------------------
ドを認識します:
...
<string>
filename(<frame>)
f = File(“c:\\config.sys”,”r”);
foreach(x,f)
<grey>
luma(<col>,<row>)
<r>,<g>,<b>
rgb(<col>,<row>)
info(x);
<ImageObject>
next(<void)
...
--------------------
以下のメソッドは L S c r i p t / P Tスクリプトにのみ利用可能で
...
す:
obj = getfirstitem(MESH);
<void>
foreach(x,obj)
<number>
info(x.name);
lumaSpot(<col>,<row>,<size>,<blend>);
...
<num>,<num>,<num>
--------------------
rgbSpot(<col>,<row>,<size>,<blend>);
...
a = @1,2,3@;
foreach(x,a)
info(x);
...
–97–
needAA(void);
generic
...
{
// テキストファイルの開始行を一行に取得します
line = File(“f:/dirs.txt”,”r”).read();
info(line);
image = getfirstitem(“IMAGE”) ||
error(“No images loaded!”);
foreach(i,image)
...
info(i.name,”:
...
“,.i.width,”,”,i.height);
}
// ベクトルにアクセスします
v[2] = <1,2,3>;
• レ イ ア ウ ト L S c r i p t に2つの関数 l o a d i m a g e ( ) と
info(v[2].x);
clearimage()が新規追加されました。これらの関数はそ
...
れぞれレイアウトのイメージリストに新規イメージファイル
を読み込み、イメージをクリア(アンロード)します。
連鎖式は代入文の左側に使用することはできません。
generic
式は代入文の右側においてのみ存在できるからです。
{
例えば、以下の文は不当でありエラーが発生します:
image = loadimage
...
(“f:/lw/cdrom/FilmImage.tga”) ||
error(“Can’t load image!”);
v[2] = <1,2,3>;
info(image.width,”,”,image.height);
clearimage(image);
...
v[2].x = 0;
}
•LScriptにおける式の連鎖が可能となりました。
...
// 配列のエレメントからファイルオブジェクトエージェントに
// アクセスします
v[3] = nil;
v[2] = File(“f:/dirs.txt”,”r”);
info(v[2].read().isStr());
...
–98–
リビジョン履歴
•モデラーのランタイムプラグインはプラグインとしてのスク
ベータ 7:
た。
リプトのアダプタメカニズムに対しうまく動作しませんでし
•5 0を超える C o m m a n d S e q u e n c eのエントリーがレイアウト
ベータ 5:LScript v2.0 ベータ 5
LScriptコンパイラの目録から抜け落ちていたため、これらの
•レイアウトのCSがビルド411を反映して更新されました。
コマンドを”external”であると判断されていました。
•CSコマンドShadowType()が誤って整数値ではなく文字列引
•浮動小数点数値の同等値テストを制御するための新規プラグ
数を想定していました。
マ指示語が追加されました。このプラグマ 'fpdepth'は小
•初期化されていない変数参照が修正されました。
数点以下の桁数を指定し、浮動小数点数値(数値、ベクトルな
ど)の同等比較時の有効桁数とします。
ベータ 6:
プラグマ設定はスクリプトのランタイム演算全体を超える定
•スクリプトコンパイラはディレクトリ分離記号のトレーリン
義域を保持しています。
@fpdepth 3
グを正しく処理していませんでした。
•言語に対しオブジェクトのマスク処理が新規追加されました。
• 関数 S e l e c t B y N a m e ( ) 、 S h a d o w T y p e ( ) そして L i g h t FalloffType()は定義されている引数の個数が不当で、どの引数
このメカニズムを使用するとマスク処理をサポートしている
を提供してもエラーが発生しました。
整数データタイプのオブジェクトがオブジェクト自身に対し”
•LS/GNとLS/MCに8つの新規CS関数を追加しました。
マスク”処理を実行できるようになります。
SaveLWSC1
このマスク処理関数の正確な戻り値はデータタイプによって
Layout_SetWindowPos
異なります。
Layout_SetWindowSize
•浮動小数点数値(数値、ベクトル)はマスク値を使用して小数
Scene_SetWindowPos
点以下の有効桁数のみをレンダリングします。
Scene_SetWindowSize
•キャラクタ文字列はマスク値を使用して左側からの文字数を
返します(strleft()関数と同等です)。
Item_SetWindowPos
•他のデータタイプは全て自身を評価します(つまりマスク処
LoadMotion
理は行われません)。オブジェクトにマスク処理を施すには、
SaveMotion
オブジェクト演算子の後に整数値をつけます。例えば、以下
のコードでは値”1.34”を表示します。
•LS-RT/GNプラグインはインストールされたコンパイル済み
...
のスクリプトに対しうまく動作しませんでした。
bob = 1.34398545;
•LightWaveのオブジェクトエージェント全てにオブジェクト
info(bob.2);
のタイプを保持するデータメンバ'genus'を持たせることにし
...
ました。ここには M E S H 、 L I G H T 、 C A M E R A 、 B O N E 、
SCENEもしくはCHANNELが入ります。
–99–
マスク演算子は変数にのみ使用が可能です。
また連鎖式にも使用できます。
レイアウトLScriptコンパイラがチャンネルフィルタースクリ
プトタイプをサポートするようになりました。
...
•アイテムモーションのLScriptが関数 create()の中にある
bob = 1.34398545;
info(bob.2.asStr().isStr());
...
メッシュオブジェクトエージェントをオプションで受け付け
// 1 を表示
るようになりました。
@script motion
•マスタークラスのL S c r i p tがランタイムプラグインを持つよ
...
うになりレイアウトLScriptコンパイラがこのタイプをサポー
create: obj
トするようになりました。
{
•一組の新規 L S c r i p tプラグインが追加され、レイアウトのチ
info(obj.filename);
ャンネルフィルタープラグインアーキテクチャへのスクリプ
}
ト機能を提供します。 'ls-df.p'と'lsrt-df.p'はテキ
...
ストであり、ランタイムはこのアーキテクチャに対するプラ
グインをサポートします。
関数process()のUDFは3つの引数を受け取ります。
1番目はチャンネルアクセスオブジェクトエージェント、2番
この引数はオプションなので、UDFの定義でオフのままにし
目はカレントのフレーム番号、そして3番目の引数はカレント
ておいても構いません。
のタイムインデックスとなります。
•可能なスクリプトタイプのプリプロセッサリストに”chan-
...
nel”スクリプトタイプが追加されました。このタイプはチャ
process: ca, frame, time
ンネルフィルターLScriptタイプを表します。
{
...
}
@script channel
...
...
チャンネルアクセスオブジェクトエージェントは1つのデータ
•L S c r i p tのオブジェクトエージェントが個々のチャンネルに
メンバ 'name' をエクスポートします。このメンバはスクリ
対しインターフェイスを提供するようになりました。
プトが適用されるチャンネルの表示可能な名称をあらわしま
新規メソッドとオブジェクトタイプを使用してオブジェクト
す。これに加え、チャンネルデータを取得・設定するための
のエンベロープチャンネルにおける反復・対話が可能になり
関数get()とset()が追加されました。
ました。
チャンネルデータは浮動小数点数値となります。
新規firstChannel() メソッドはオブジェクトにつけられ
get()ではタイムインデックスを必要とします。
ている最初のチャンネルを返します。 firstChild() メソ
set()は関数 process()のUDFで提供されたタイムインデ
ッドと同様、このメソッドも全てのチャンネルを通し反復の
ックスにおけるチャンネルの新しい値を受け付けます。
プリフェースとして使用されなければなりません。
–100–
nextChannel()メソッドではオブジェクトに対するチャン
event()
このメソッドを使用してチャンネル上でイベントが発生
する度に呼び出されるコールバック関数を起動します。
ネルリストにおける次のチャンネルを返します。
エンベロープ内のキーフレームの作成・削除またはキー
両メソッドとも利用可能なチャンネルが(それ以上)存在しない
フレーム値の変更といったイベントです。
場合には'nil'を返します。
light = getfirstitem(LIGHT);
以下のチャンネルフィルタースクリプトは新規オブジェクト
c = light.firstChannel();
エージェントの使用法を説明します。
while(c)
@warnings
{
@script channel
...
@version 2.0
c = light.nextChannel();
}
create: channel
{
•LScriptのOAツールセットにチャンネルオブジェクトエージ
ェントが新規追加されました。新規オブジェクトエージェン
light = getfirstitem(LIGHT);
トは個々のチャンネル機能へ構造化されたインターフェイス
c = light.firstChannel();
を提供します。
while(c)
{
新規OAメソッドである firstChannel() とnextChan-
last if c.name == “Position.X”;
c = light.nextChannel();
nel()は新規OAタイプを返します。ある環境においては、チ
ャンネルオブジェクトエージェントがUDFに対し提供されま
c.event(“lightEvent”);
す(チャンネルフィルターLScriptに対しては関数 create()
}
のUDFが提供されるように)。
}
このリリースではチャンネルオブジェクトエージェントは以
// このチャンネル内における変更と同期を保ちます
下のデータメンバをエクスポートします
name
type
レイアウトインターフェイス上に表記されるチャンネル
process: ca, frame, time
名称(Graph Editorなどのように)
{
ca.set(0.0);
チャンネルのタイプ。以下の値のうちの一つとなりま
す: NUMBER, DISTANCE,PERCENT, ANGLE
}
lightEvent: channel,event
// チャンネルオブジェクトエージェントイベントコード
2つのメソッドが利用可能です:
{
value()
このメソッドでは特定の時間においてチャンネルが評価
されます。返り値はチャンネルのタイプに基づいて補間
された浮動小数点値となります。
// Lightの”Position.X”チャンネルに何かが起こりました
info(event);
}
–101–
•タブと改行( '\t'と'\n')に対するC言語仕様のエスケープ
•シーンオブジェクトエージェントにレンダリングで使用され
シークエンスがサポートされるようになりました。
る整数反復深度を保持するデータメンバ
•文字列の値を取得しそれに対応する整数値を返す変換関数
'recursiondepth'が追加されました。
ascii()が追加されました。非表示の文字を比較する際に便
利です。
•レイアウトオブジェクトエージェントは4つの新規データメ
ンバをサポートするようになりました。これらのメンバは状
if(ascii(line[x]) == '\t’)
...
態を表すブーリアンフラグです。
selected
childrenvisible
•変換式'asAsc'が追加されました。
channelsvisible
if(line[x].asAsc == '\t’)
...
locked
•文字列インデックスが誤ってハンドルされ、アプリケーショ
•L S c r i p tでコンパイルされたイメージチャンクがランタイム
ンがクラッシュしていました。
システムでは適切に認識されませんでした。
•関数SubPatchLevel()はレイアウトへ不当な型の引数整
数値の代わりに浮動小数点数値を渡していました。
ベータ 4:
•シーンオブジェクトエージェントにカレントシーンを通じて
オブジェクトの選択をサイクルするための2つの反復メソッド
•関数 g e t f i l e ( )で使用されるバッファサイズが標準のOS
が追加されました。
のバッファサイズ2 5 6バイトの半分よりも少ないサイズとな
firstSelect()とnextSelect()メソッドは他の反復メ
っていました。
ソッド、例えばレイアウトオブジェクトエージェントの
•正規表現がデバッガデータセットに追加されました。
firstChild()やnextChild()と同様の形式で使用され
•debug()コマンドは既にデバッグ中であるかを確認してい
ます。
ませんでした。
scene = getfirstitem(SCENE);
•レイアウトのCSはビルド402を反映して更新されました。
obj = scene.firstSelect();
•レイアウトのCS関数は(SelectItem()やGoalItem()の
while(obj)
ように)引数としてアイテムのIDが想定されていますが、必要
{
とされるレイアウトオブジェクトを指定できるように引数の
...
組み合わせを変更できるようにしました。
obj = scene.nextSelect();
•LightWaveのシーンファイルにおいてフォーマットされてい
}
るように整数値で指定することが可能です。指定する値は16
進数であるため、ビット演算を行い32ビット整数値へ配置し
•シーンオブジェクトエージェントにレイアウトインターフェ
なおす必要もあります。
イス内で現在選択されているタイムインデックスを保持する
データメンバ'currenttime'が追加されました。
–102–
ベータ 3:
// 2番目のメッシュオブジェクトを選択します
SelectItem((1 << 28) | 1);
•反復foreach()で受け入れられるデータタイプに連想配列
タイプが追加されました。キーの値は内部ハッシュツリー内
•カレントシーンにおけるオブジェクト名称を評価するための
でみつかる順に処理されます。
文字列値が提供されます。
•アイテムモーションの set() 関数はパラメーター(2)の値を
正しく受け付けていませんでした。
•オブジェクトクラスは (MESH、LIGHT、CAMERA) と、そ
•多くのオブジェクトベースの参照問題がアドレス指定されま
れに続く整数値で特定されます。整数値はクラスのオブジェ
した。
クトリスト内におけるオブジェクトのリニアオフセット(基底
•今まではある状況においてレイアウトL S c r i p tへの再入に問
は1)を特定する値です。
題が生じていました。
// シーン内の3番目のLightを選択します
SelectItem(LIGHT,3);
特定の例をあげると、単一のプラグインが相互依存している2
つ以上のオブジェクト(インスタンス)を管理している場合、既
•以下のレイアウトC S関数は新規オブジェクトに名称をつけ
にプラグインがある process()関数の中にいる状態で、プ
るためにオプションのキャラクタ文字列を受け付けるように
ラグインの process()関数が呼び出される可能性がありま
なりました。名称が提供されない場合には、レイアウトはユ
した。LScriptはグローバル変数を使用(歴史的な経緯から)し
ーザーに対しリクエスタを表示します。
ているため、この状況においてはハンドルすることが不可能
AddNull
です。
この再入の問題を解決するためにレイアウトLScriptにインス
AddBone
タンススタックが実現しました。これにより2つ以上のオブジ
AddChildBone
ェクトにそれぞれ同種類のLScriptプラグインが適用されてい
AddDistantLight
る場合でも、相互依存が可能となりました。
AddPointLight
ここに以前のバージョンのレイアウトLScriptではクラッシュ
する可能性が高かった相互依存の例を紹介します(Alexandre
AddSpotlight
Bonから提供された例に基づいています)。
AddLinearLight
1.シーンに3つのヌルを追加し、”A”、”B”、”C”と名称をつけま
AddAreaLight
す。
2.ヌル”A”にモーションをつけます。
3.ヌル”C”の下にItem Motionのスクリプトを適用し“B”
ReplaceWithObject
ReplaceWithNull
を監視するようにします。
LoadObject
4. 同じスクリプトを今度はヌル”B”に対して適用し、“A”を監
視するようにします。
•基盤となるプラグインAPIにおいて変更が生じたため、以下
5. アニメーションを走らせます。
のサーフェイスに関するLScript関数が削除されました:
_getRawSurf()
_setRawSurf()
–103–
•L S c r i p tのコンパイラはコンパイル済みのスクリプトファイ
@version 2.0
ルに記憶されているデータタイプに対し不正なサイズを使用
@script motion
していました。
•ランタイムプラグインは古いインターフェイスのバージョン
parent;
値を使用していたため、レイアウトから渡されるインターフ
process: ma, frame, time
ェイス構造体の中のエレメントが初期化されていませんでし
{
た。プラグインがこれらのNULL値を参照すると、クラッシュ
if(!parent) return;
します。
newpos = parent.param(POSITION,time);
•レイアウト L S c r i p tコンパイラは選択したソーススクリプト
newpos.z -= 2;
内で"@script"プラグマを検出すると、自動的にプラグイ
ma.set(POSITION,newpos);
ンアーキテクチャを選択するようになりました。
}
•LScriptのプリプロセッサはスクリプト内に " @ s c r i p t " プ
options
ラグマを検出すると、アーキテクチャに対し正しいタイプで
{
あるかを確認するためにチェックを行うようになりました。
if(!reqbegin(“Follow The Leader”))
return;
•LScriptプラグインサーバー名称が標準化されました。
名称の一部としてレイアウトにアーキテクチャタイプを表示
c1 = ctlallitems(“Select
parent”,parent);
if(reqpost())
する代わりに(コンテキストポップアップメニューにおいての
みプラグインが表示されるため冗長となっていましたが)、全
て以下の名称をもつことになりました:
parent = getvalue(c1);
•“LW_LScript”
reqend();
これはテキストベースのスクリプトインタープリターに対す
}
る新規名称です。プラグイン名称をLScript/GN、LScript/MC
やLScript/IFなどのように置き換えます。
•L S c r i p tの仮想マシンコードにおけるマイナーな改良がいく
•“LW_LScript/RT”
つか行われました。
これにより代入文の左側にオブジェクトベースの配列参照が
これはバイナリベースのスクリプトインタープリター用の新
使用できるようになりました:
規名称です。プラグイン名称を L S / G N - R T、L S / D M - R Tや
LS/IF-RTなどのように置き換えます。
v[1] = <1,2,3>;
•“LW_LSCompiler”
v[1].x = 10;
. . .
LScriptコンパイラプラグイン用の新規名称です。
t = 1;
LSC/LWやLSC/MDに置き換えます。
obj[t] = ObjectMan(“Cow.lwo”);
obj[t].surfaces[t] += “_Bob”;
–104–
ベータ 2:
LScript最新情報について
•終端にコンマ分離記号が埋め込まれている文字列があり、以
LScriptは、大小のさまざまなバージョンアップ・リビジョン
下に続く文字列と連鎖していました。このため特定のオブジ
アップを行っています。
ェクトメソッド名称が認識されませんでした。
これにあわせて、ドキュメンテーションも常に追加されてい
•array()関数はいまだに古い形式で配列を生成していたた
ます。
め結果配列にアクセスされると問題が生じていました。
LScript最新情報については、以下のウェブサイトをご覧にな
•再帰的関数は配列内の全てのエレメントを特定のデータタイ
ることをおすすめします。
プで初期化しなければならないのに、配列が持つサブ配列を
http://www.newtek-outpost.com/employees/bobh/
破壊していました。
•ある特定の状況においてオブジェクトデータメンバは不当な
オーナーに連結されていました。
•ある理由により、不可視(オフ)ではない状態の ctltext()
コントロールを不可視にした場合に、パネルがクラッシュし
ます。不可視状態の ctltext()の値は当分の間サポートさ
れません。
•サブ配列が参照された時点で配列処理にバグが起こります。
–105–
LScpirt Ver.2.0 日本語マニュアル
©1997−2000 NewTek,Inc./DSTORM,Inc.
All Rights Reserved
–106–
索引
記号その他
?,: 7
A
abs 17
acos 17
addcurve 46
addfilename 55
addhsv 55
additems 55
addpoint 45
addpolygon 45
addquad 46
addrgb 55
addtriangle 46
alignpols 34
append 22
asin 17
assigndata 72
atan 17
autoflex 28
axisdrill 32
C
cache 58
ceil 17
center 20
changesurface 36
cleanup 60
close 13
cmdseq 38
continue 8
copy 26
copysurface 37
cos 17
cosh 17
cot 17
create 49
createsurface 37
csc 17
ctlchoice 41
ctlcolor 41, 42
ctldistance 41
ctlfont 41, 42
ctlinteger 41
ctlnumber 41
B
ctlstring 41
bend 29
ctlsurface 41, 42
bevel 33
ctltext 41, 42
bglayers 39
ctlvector 41
boolean 33
cut 26
boundingbox 44
bufferline 57
D
deformregion 28
deg 18
frac 19
delete 26
fracsubdivide 34
destroy 49
freezecurves 34
destructor 72
G
dump 24
get 62
E
getdefaultsurface 36
editbegin 44
getdir 23
editend 44
getempty 39
eof 13
getemptybg 39
error 19
getemptyfg 39
exp 16
getenv 23
extent 20
getfile 38
extrude 31
getfirstitem 50
F
getvalue 42
fac 19
H
fglayers 39
hypot 18
file 19
I
filedelete 20
if/else 6
fileexists 20
illuminate 61
fixedflex 27
info 19
flags 56, 60, 62
init 60
flip 34
integer 21
floatline 57
isOpen 12
floor 17
fontclear 38
fontcount 37
J
jitter 29
fontindex 37
L
fontload 38
lathe 31
fontname 37
line 14
for 7
linecount 14
listadd 43
listremove 43
move 28
N
load 26
new 26
Load 49
newtime 60, 62
loadscene 64
nextsurface 36
log 16
nl 14
lyrbg 26
number 21
lyrdata 27
lyrempty 27
lyremptybg 27
lyrfg 26
lyrsetbg 27
lyrsetfg 27
lyrswap 27
M
magnet 28
makeball 30
makebox 30
makecone 30
makedisc 30
maketesball 30
maketext 31
max 17
mergepoints 30
min 17
mirror 31
mod 18
monend 40, 59
moninit 39, 59
monstep 40, 59
O
offset 15
open 12
options 49
owndata 72
ownmethod 72
P
parse 13, 20
paste 26
pathclone 32
pathextrude 32
pointcount 45
pointinfo 47
pointmove 47
pole 29
polycount 45
polyinfo 46
polynormal 47
polypointcount 46
polypoints 47
polysurface 47
pow 18
process 49
processrgb 57
Q
quantize 30
S
save 26, 49
savescene 64
scale 29
R
rad 18
railclone 32
railextrude 32
random 17
randu 17
range 18
raytrace 62
read 13
readByte 14
readInt 14
readNumber 13
readVector 13
recall 24
removepols 34
rempoint 47
rempolygon 47
renamesurface 37
reopen 12
reqbegin 40
reqend 40
reqpost 41
returndata 72
rewind 13
rotate 28
round 19
sec 17
select 18
selhide 36
selinvert 36
selmode 43
selpoint 34
selpolygon 35
selunhide 36
set 62
setalpha 57
setblayer 26
setlayer 26
setrbg 57
setsurface 36
setvalue 43
shapebevel 33
shear 28
sin 17
sinh 17
size 21
sleep 23
smooth 30
smoothshift 33
soliddrill 33
spawn 22
split 21
sqrt 16
step 19
write 13
store 24
writeByte 14
string 21
writeInt 14
strleft 24
writeln 13
strlower 24
writeNumber 14
strright 24
strsub 24
strupper 24
subdivide 34
swaplayers 38
switch/select 7
T
tan 17
tanh 17
taper 29
terminate 23
triple 34
twist 29
U
undo 26
unifypols 34
V
vector 21
version 73
vmag 19
vortex 29
W
wait 23
warn 19
while 6
Y
yremptyfg 27