11 Processing モンタージュ スケッチ
ControlP5ライブラリをインストールしたので、その使い方に慣れるため、「montage」という名前の新しいスケッチを作成します。モンタージュ(顔の合成)は、目撃者の記憶から目や鼻などの特徴を合成し作成される顔画像のことで、実際には高度のコンピュータソフトウェアを使用しまが、ここで紹介するモンタージュプログラムは、単純化した線画で顔画像を構成する簡易的なものですが、それでも楽しく遊ぶことができます。
顔の輪郭を描く
Processingに新規スケッチを作成し、まず、次のコードを追加します。
import controlP5.*;
ControlP5 cp5;
void setup() {
size(720,485);
cp5 = new ControlP5(this);
}
void draw() {
background(#004477);
stroke(#FFFFFF);
strokeWeight(3);
int axis = 250;
// face
noFill();
ellipse(axis,220, 370,370);
}
先頭には ProcessingにControlP5を読み込むための行 'import controlP5.*'; が必要です。さらに、新しいControlP5インスタンスを、名前 cp5 の変数に割り当てます。これ以降、cp5.プレフィックスを付けてContolP5関数にアクセスできます。
setupブロックの、axis変数は、ellipseの中心を通る座標、言い換えれば、顔の縦方向の中心を決定します。
この状態で実行すれば、顔の輪郭として円が画面の左側に描かれ、右側にコントロールウィジェット用のスペースを確保します。
最初のウィジェットはテキストフィールドになります。setup関数内に追加します。
void setup() {
...
cp5.addTextfield("alias")
.setPosition(500,20)
.setSize(200,25)
;
表題の入力と表示
cp5.addTextfield()行の最初の引数に名前を指定します。この場合、'alias'を使用しました。この名前は、これ以降にコントローラーを参照するために使用され、フィールドのデフォルトのラベルとしても使用されます。
draw関数では、入力した内容を取得し、text()関数を使用して取得内容をレンダリングします。このgetメソッドを使用して、任意の(名前で)cp5コントローラーのプロパティにアクセスし、getText()を使いテキスト値だけを分離します。
void draw() {
...
// alias
fill(#FFFFFF);
textSize(20);
textAlign(CENTER);
String alias = cp5.get(Textfield.class,"alias")
.getText();
text(alias, axis,450);
noFill();
入力フィールドに文字を入力してテストします。入力した文字が顔の下に表示されます。
目を描く
次に、目を制御するための'Slider'ウィジェットを追加します。追加するメソッドは、setRange()及び setValue()、それぞれ、最小値/最大値の設定、初期値の設定です。
void setup() {
...
cp5.addSlider("eyeDistance")
.setPosition(500,80)
.setSize(200,20)
.setRange(30,120)
.setValue(80)
;
問題は、スライダーラベルのデフォルトの位置がウィジェットの右側にあることです。これでは、このレイアウトからはみ出てしまします。左下にラベルを再配置するために、配置とパディングを調整するコードを追加します。
...
.setValue(80)
;
cp5.getController("eyeDistance")
.getCaptionLabel()
.align(ControlP5.LEFT, ControlP5.BOTTOM_OUTSIDE)
.setPaddingX(0)
;
顔に目を描くために、さらに3つのコントロールウィジェット(ノブと2つのトグル)を追加します。
void setup() {
...
cp5.addKnob("eyeSize")
.setPosition(515,135)
.setRadius(35)
.setRange(10,60)
.setValue(50)
;
cp5.addToggle("heavybrow")
.setPosition(635,138)
.setSize(20,20)
;
cp5.addToggle("sleepless")
.setPosition(635,185)
.setSize(20,20)
;
各コントロールからデータを取得し目を描くために、draw関数に次の行を追加します。各コントローラープロパティを取得するためにコントローラーの名前のついた変数が使用されています。テキストフィールドの場合よりかなり簡素化されています。
この簡素化された方法を使用するには、コントローラーの名前のついた変数を共通変数としてスケッチの上部で宣言する必要があります。
import controlP5.*;
ControlP5 cp5;
int eyeDistance;
int eyeSize;
boolean heavybrow;
boolean sleepless;
void setup() {
...
void draw() {
...
// eyes
ellipse(axis-eyeDistance,180, eyeSize,eyeSize);
ellipse(axis+eyeDistance,180, eyeSize,eyeSize);
if(heavybrow == true){
fill(#004477); stroke(#004477);
rect(100,180-eyeSize/2, 300,eyeSize/2);
stroke(#FFFFFF);
line(
axis-eyeDistance-eyeSize/2-5, 180,
axis+eyeDistance+eyeSize/2+5, 180
);
}
if(sleepless == true){
noFill();
arc(axis-eyeDistance,190,
eyeSize,eyeSize, 0,HALF_PI);
arc(axis+eyeDistance,190,
eyeSize,eyeSize, HALF_PI,2.5);
fill(#004477);
}
スケッチを実行して、目の表情をいろいろ変化させて遊んでみてください。
鼻を描く
鼻には、2Dスライダーを追加します。口は標準のスライダーですが、増分を設定するための目盛りが付いています。
...
Slider2D s;
int mouthWidth;
void setup() {
...
s = cp5.addSlider2D("nosePosition")
.setPosition(500,240)
.setSize(200,100)
.setMinMax(-30,-20,30,20)
.setValue(0,0)
;
cp5.addSlider("mouthWidth")
.setPosition(500,375)
.setSize(200,20)
.setRange(10,200)
.setValue(124)
.setNumberOfTickMarks(6)
.setSliderMode(Slider.FLEXIBLE)
;
cp5.getController("mouthWidth")
.getCaptionLabel()
.align(ControlP5.LEFT, ControlP5.BOTTOM_OUTSIDE)
.setPaddingX(0)
.setPaddingY(12)
;
}
void draw() {
...
// nose
float nosex = s.getArrayValue()[0];
float nosey = s.getArrayValue()[1];
line(axis-10+nosex,180+nosey,
axis-10+nosex,300+nosey);
line(axis-10+nosex,300+nosey,
axis-10+nosex+30,300+nosey);
// mouth
line(axis-mouthWidth/2,340, axis+mouthWidth/2,340);
2Dスライダーは、リストに2つの値を保持するため、 .getArrayValue()白い角括弧が表示されます。さまざまなメソッドが何を制御するかについて混乱している場合は、引数を調整して、これがどのような影響を与えるかを確認してください。
画像ファイルとして保存する
作成した画像をTIFFファイルとして保存する最後のボタンウィジェットを1つ追加します。この.addButton()メソッドを使用して、表示ウィンドウの右下に新しいボタンを配置します。
void setup() {
...
cp5.addButton("saveImage")
.setPosition(500,440)
.setSize(200,25)
;
スケッチの最後に、以下の関数を追加し、ボタンのクリックで画像ファイルを出力します。
import controlP5.*;
...
void setup() {
...
}
void draw() {
...
}
void saveImage() {
save("drawing");
}
上記のように拡張子を付けずにファイル名を指定した場合、.tif ファイルで保存します。もし他の形式で保存したい場合は、.jpg .png などの拡張子をファイル名に付けてを指定します。
この記事は、Processing.py in Ten Lessons – 7.5: ControlP5 を元にして作成させていただきました。
参考までに、montage スケッチを掲載します。
---> montage.zip
次回は、ControlP5の主要コントロールの使い方を詳しく調べます。