先の章まで見てきたオブジェクト形状では、プログラムの残りの部分で相互に操作するのに script 変数を使いました。ツールスクリプトではそれとは異なる window という変数を使います。これはスクリプトの実行から、そのウインドウ (artofillusion.LayoutWindow) への参照です。以下の例で、ツールスクリプトでできるいくつかをお見せします。
シーン内の球をひとつずつ選択する、とても単純なツールスクリプトです。
scene = window.getScene(); for (i = 0; i < scene.getNumObjects(); i++) if (scene.getObject(i).getObject() instanceof Sphere) window.addToSelection(i);
実行するには、ツール → スクリプト編集... を選択します。スクリプトを直接打ち込むか貼り付けるかして、「実行」をクリックします。
このスクリプトは単純で、説明をほとんど要しません。形状スクリプトから script.getScene() を呼び出したのと同じように window.getScene() を呼び出して、シーンの参照を取得します。シーン内の各オブジェクトについてループします。scene.getObject(i) が ObjectInfo を返し、対応する Object3D を getObject() が返します。オブジェクトが球なら、window.addToSelection() を呼び出して選択します。
もう少し複雑なスクリプトを紹介します。"glass" という名前のテクスチャを探して、選択中のオブジェクトすべてがこのテクスチャを使うよう設定します。
scene = window.getScene(); glass = scene.getTexture("glass"); if (glass == null) { new MessageDialog(window, "There is no texture called 'glass'."); return; } for (i = 0; i < scene.getNumObjects(); i++) if (window.isObjectSelected(i)) scene.getObject(i).setTexture(glass, glass.getDefaultMapping(scene.getObject(i).getObject()));
"glass" という名前のテクスチャがなければ警告メッセージを表示し、すぐに元に戻ります。これは、自身のユーザインターフェイスを実際に表示するスクリプトとしては、今まで紹介した中で初めてのものです。些末な例ではありますが、インターフェイスはこのような単純なメッセージ表示に限定されません。以下はもっと凝った例(巻貝の貝殻)です。
まず、ユーザにさまざまなパラメータの入力を促し、それらを元に貝殻を作成します。ValueField, ComponentsDialog, MessageDialog(上述のスクリプトで使用したもの)はすべて、artofillusion.ui パッケージ内のクラスです。
lengthField = new ValueField(30, ValueField.POSITIVE+ValueField.INTEGER); heightField = new ValueField(0.1, ValueField.POSITIVE); widthField = new ValueField(0.05, ValueField.POSITIVE); thicknessField = new ValueField(0.1, ValueField.POSITIVE); dlg = new ComponentsDialog(window, "Select Parameters for Seashell", new Widget [] {lengthField, heightField, widthField, thicknessField}, new String [] {"Length", "Height Scale", "Width Scale", "Thickness Scale"}); if (!dlg.clickedOk()) return; numVert = lengthField.getValue(); heightScale = heightField.getValue(); widthScale = widthField.getValue(); thicknessScale = thicknessField.getValue(); vert = new Vec3 [numVert]; rad = new double [numVert]; smooth = new float [numVert]; height = new double [numVert]; for (i = 0; i < numVert; i++) { angle = i*0.25*Math.PI; rad[i] = thicknessScale*angle; height[i] = heightScale*angle; if (i >= 8) height[i] += height[i-8]; vert[i] = new Vec3(widthScale*angle*Math.cos(angle), height[i], widthScale*angle*Math.sin(angle)); smooth[i] = 1.0f; } shell = new Tube(vert, smooth, rad, Tube.INTERPOLATING, Tube.OPEN_ENDS); window.addObject(shell, new CoordinateSystem(), "Seashell", null);
このスクリプトは当然、何度も使うためのもので、一度実行したら破棄するものではありません。スクリプト編集ウインドウ内の "Load" ボタンと "Save" ボタンで、このスクリプトをディスクから読み込んだり、ディスクに保存したりできます。
このスクリプトを ArtOfIllusion/Scripts/Tools ディレクトリに保存してみましょう。ファイル名は Seashell.bsh とします。ツールメニューを見ると、新規のアイテム "Seashell" がスクリプトのサブメニューに表示されているのが分かります。このディレクトリに保存されたスクリプトはすべて、ツールメニューに自動で追加されます。これで Art of Illusion に新規のコマンドを追加できます。
さらにもう少し複雑なスクリプトです。これはたくさんの画像の「バッチレンダリング」を一度に行います。このスクリプトはユーザに、シーンファイルフォルダと、さまざまなレンダリングオプションの選択を促します。そしてフォルダ内の各シーンでループし、それぞれを読み込み、シーン内のそれぞれのカメラの視点で画像をレンダー、JPEG 画像としてディスクに保存します。
// Prompt the user to select a directory. fc = new BFileChooser(BFileChooser.SELECT_FOLDER, "Select a Folder of Scene Files"); if (!fc.showDialog(window)) return; // Prompt the user for other options. rendererChoice = new BComboBox(); renderers = PluginRegistry.getPlugins(Renderer.class); for (i = 0; i < renderers.size(); i++) rendererChoice.add(renderers.get(i).getName()); widthField = new ValueField(400, ValueField.POSITIVE+ValueField.INTEGER); heightField = new ValueField(300, ValueField.POSITIVE+ValueField.INTEGER); qualitySlider = new ValueSlider(0, 100, 100, 80); dlg = new ComponentsDialog(window, "Select Parameters for Rendered Images", new Widget [] {rendererChoice, widthField, heightField, qualitySlider}, new String [] {"Renderer", "Width", "Height", "Quality"}); if (!dlg.clickedOk()) return; rend = renderers.get(rendererChoice.getSelectedIndex()); width = (int) widthField.getValue(); height = (int) heightField.getValue(); quality = (int) qualitySlider.getValue(); // Display the main configuration panel for the renderer. dlg = new PanelDialog(window, "Select Rendering Options", rend.getConfigPanel()); if (!dlg.clickedOk()) return; rend.recordConfiguration(); // Loop over files in the directory. dir = fc.getSelectedFile(); files = dir.list(); for (i = 0; i < files.length; i++) { if (!files[i].endsWith(".aoi")) continue; // Load the scene and find the cameras in it. sc = new Scene(new File(dir, files[i]), true); for (j = 0; j < sc.getNumObjects(); j++) { obj = sc.getObject(j); if (!(obj.getObject() instanceof SceneCamera)) continue; // Render an image and save it to disk. print("Rendering "+files[i]+" from camera "+obj.name); image = obj.getObject().renderScene(sc, width, height, rend, obj.coords); filename = files[i].substring(0, files[i].length()-4)+" "+obj.name+".jpg"; outfile = new File(dir, filename); ImageSaver.saveImage(image, outfile, ImageSaver.FORMAT_JPEG, quality); } }
これまで紹介した中で最も長いスクリプトですが、新規の要素はわずかです。PluginRegistry.getPlugins() で、インストール済みのすべてのレンダラーのリストを呼び出していることに注目してください。レンダラー(artofillusion.Renderer)は、Art of Illusion で使う多くのタイプのプラグインのうちの1つです。ユーザがレンダラーを1つ選択すると、getConfigPanel() を呼び出します。これは、そのレンダラー用の設定オプションパネルを返します。そして recordConfiguration() を呼び出して、選択されたオプションを実際に記録します。
ディスクからシーンを読み込むのは簡単です。Scene オブジェクトコンストラクタに単に File オブジェクトを渡すだけです。レンダーは、renderScene() を SceneCamera に呼び出して実行します。これは画像を同期でレンダーします(つまり、このメソッドはレンダーが完了するまで何も返しません)。またはレンダラーの renderScene() メソッドを呼び出して、非同期の画像レンダーをすることもできます。最後に ImageSaver クラスを使って、JPEG フォーマットで画像をディスクに保存します。