もっと良い解決方法は、これらのパラメータをユーザが編集できるようにすることです。これで必要なプラグインは1つだけとなり、ストライプの色や幅にこだわらずに済みます。パラメータを編集するには、ユーザインターフェイスが必要です。
すべての Texture クラスには edit() メソッドがあります。これを呼び出すとユーザインターフェイスを表示し、ユーザはテクスチャを編集できます。Stripes テクスチャの2番目のバージョンに、これを追加します。すべてのソースコードは Stripes2.java です。以下が edit() メソッドです。
public void edit(Frame fr, Scene sc)
{
RGBColor oldColor1 = color1.duplicate(), oldColor2 = color2.duplicate();
float oldWidth = width;
final Panel color1Patch = color1.getSample(50, 30), color2Patch = color2.getSample(50, 30);
final ValueSlider widthSlider = new ValueSlider(0.0, 1.0, 100, width);
final MaterialPreviewer preview = new MaterialPreviewer(this, null, 200, 160);
final Frame parent = fr;
TextField nameField = new TextField(getName());
ComponentsDialog dlg;
color1Patch.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
new ColorChooser(parent, "Color 1", color1);
color1Patch.setBackground(color1.getColor());
color1Patch.repaint();
preview.render();
}
});
color2Patch.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
new ColorChooser(parent, "Color 2", color2);
color2Patch.setBackground(color2.getColor());
color2Patch.repaint();
preview.render();
}
});
widthSlider.addAdjustmentListener(new AdjustmentListener()
{
public void adjustmentValueChanged(AdjustmentEvent e)
{
width = (float) widthSlider.getValue();
preview.render();
}
});
dlg = new ComponentsDialog(parent, getName(),
new Component [] {preview, nameField, color1Patch, color2Patch, widthSlider},
new String [] {"", "Name", "Color 1", "Color 2", "Stripe Width"});
if (!dlg.clickedOk())
{
color1.copy(oldColor1);
color2.copy(oldColor2);
width = oldWidth;
}
else
setName(nameField.getText());
}
このメソッドは複雑な感じですが、何をするか、の部分は驚くほど短いです。ご覧のとおり Art of Illusion はこの例のように、単純なユーザインターフェイスの作成を簡単にするよう特に設計されたクラスをたくさん持っています。これらのクラスは第6章で解説します。今はこのあたりはあまり気にしないでください。ここでは、このメソッドの動作をよく理解することに集中しましょう。以下の図は編集ウインドウです。

まだ完全ではありません。前の章では、事は簡単でした。Stripes1 の各オブジェクトはほかの1つ1つと同一でした。今回からは違います。Stripes2 の各オブジェクトは潜在的にほかのものとは違い、これは Stripes2 テクスチャを含むシーンがディスクを保存するとき、パラメータ値を同じように保存する必要があることを意味します。Texture サブクラスすべては、それ自身を読み込み・保存するルーチンを提供しなければなりません。Stripes2 での実装は以下となります。
public Stripes2(DataInputStream in, Scene theScene) throws IOException, InvalidObjectException
{
setName(in.readUTF());
color1 = new RGBColor(in);
color2 = new RGBColor(in);
width = in.readFloat();
}
public void writeToFile(DataOutputStream out, Scene theScene) throws IOException
{
out.writeUTF(getName());
color1.writeToFile(out);
color2.writeToFile(out);
out.writeFloat(width);
}
writeToFile() でテクスチャの変数パラメータを名前も含めてすべて、DataOutputStream に保存します。これは、DataOutputStream からパラメータ値を読むコンストラクタによって整合されます。2つのメソッドの互換性を確認できる限り、パラメータはどのようなフォーマットでも保存できます。
最後に、すべてのテクスチャは duplicate() メソッドを提供する必要があります。これはそれ自身の正確なコピーを作成します。Stripes2 での実装は以下です。
public Texture duplicate()
{
Stripes2 s = new Stripes2();
s.color1.copy(color1);
s.color2.copy(color2);
s.width = width;
return s;
}