オブジェクトの削除
shadeスクリプトにはまっているので、引き続き、試している。
今回は、オブジェクトの削除について、スクリプトでやってみた。
ブラウザで右クリック→削除(GUI)
まずは、スクリプトを使用せず、通常のオブジェクトの削除の仕方。タイトルの通りなので、書くまでもないが、下の図のような感じになっている。

ブラウザで選択>右クリック>削除を左クリック。
削除自体は、簡単すぎて、文章にならない。(CUI)
スクリプトで、オブジェクトを削除するには、
xshade.scene().active_shape().remove()
の、一行で終わってしまう。
簡単すぎて、文章にならない。
しかし、自分がアニメーション作るときには、もう少し、工夫する必要があった。
消したいものだけを消したい。
上の一行で、オブジェクトを消すのであれば、前もって、消したいオブジェクトを選択していなければならない。
なので、どうやって、消したいものだけを選択するのかという問題がある。
- うまい具合に、そのオブジェクトを選択できる
- そもそもシーン全体に、オブジェクトが一つしかない
なら、上の一行だけでもいい。
しかし、無数にオブジェクトがある場合、しかも、それがパート(フォルダ)別に分かれていない場合は、慎重に、消したいものを選択する必要がある。
remove()するために、選択する必要はあるだろうか。
実は、選択する必要は、ない。
GUIでは、選択する必要があったが、CUIでは、必ずしも選択する必要は、ない。
そもそも、上の一行を使う際、選択する必要があるのは、xshade.scene().active_shape()を使って、形状を取得しているからだ。
- xshade.scene().active_shape()で、選択状態にある 形状が返ってくる。
- その形状のメソッドに、remove()とか、surface.diffuseとかいろいろなものがある
だから、形状に色々な情報が付加できる。だから、選択する必要があった。
ただの、オブジェクト指向のやつですね。
形状が返ってくる変数は、xshade.scene().active_shape()だけじゃない。
xshade.scene().active_shape()では、選択している必要があるけど、それ以外はそうでもない。
選択しなくてもいい形状の操作のためには
xshade.scene().active_shape()以外の”形状を返す”操作のメソッドとして、remove()すればいい。
(例)形状.remove()
こんな感じで。
とはいえ、shadeリファレンス内部は、ほとんどすべて、xshade.scene().active_shape()を使って説明されている。
他の方法は、あまりやられていない。
とりあえず、形状を返すコマンドを、リファレンスから拾い読みしてみた。
これらのコマンドを使えば、選択しないで、削除(以外の操作も)できる。
表 形状を返すコマンド。
コマンド名 | 説明1 | 説明2 |
---|
active_shape() | 代表例。選択されている形状を返す | |
get_shape_by_name | 指定した名前を持つ形状を返す | 1個目の引き数で文字列で名前((例)”object”)。第二引数にブール(TrueもしくはFalse)がいる。デファルトで設定される名前を指定する場合には、Trueを設定する必要がある。 |
get_shape_by_ordinal | 序数で指定された形状を返す | ルートパートを0として、パート等含め、パートを全部展開したときの、ブラウザの上からの順序。3つ位作ってprint xshade.scene().get_shape_by_ordinal(3).nameとかやれば、形状の名前が返ってくるはず。 |
get_shape_by_position | ブラウザ上の位置から形状を返す | 引数にリストをとれる。パート内部の込み入った順序を、リストの形で表現できる。[3,2,3]とか。ちなみに[3,0]や、最後よりも一つ多い場合、当然、sentinel(番兵)が返ってくる。2つ以上多い場合はエラー。-1以下の場合、パートが返ってくる。 |
get_shape_by_uuid | uuidで指定された形状を返す | uuidを指定する。uuidは、文字列みたいに、クォーテーションマーク(もしくはダブルクォーテーション)で囲む。 |
get_shapes_by_name | 指定された名前を持つ形状のタプルを返す | これだけ、shapes と複数形なのに注意。球(デファルト名)を複数作ってから、全部選択せずに、操作したい場合、print xshade.scene().get_shapes_by_name(‘球’,True)[0].surface.diffuseとか書く。あくまでも、タプルなので、インデキシングしないとだめ。全部まとめていっぺんに処理できない。forなどされたし。 |
memorized_shape | 記憶されている形状を返す | xshade.scene().memory()とセットで使う。(記憶したい形状を選択中に、)xshade.scene().memory()を実行。他の形状を選択した後、(スクリプトをいったん全部消して)xshade.scene().memorized_shape().activate()を実行すると、さっき記憶した形状が選択されているはず。 |
当然ではありますが、xshade.scene().active_shape()のように、xshade.scene() を付けて使う。
xshade.scene()自体を、変数名で宣言したっていい。そうして説明している部分も、リファレンス内にあった。
- 変数名(オブジェクト名?)をつけて削除
- オブジェクトに名前を付けて削除
色々やってみた。
その結果、「remove()をつかって削除」、というよりも、「各オブジェクトに、どうやって名前を付けるか」という内容になってしまった。
前もって、変数として宣言しておくタイプ
object01 = xshade.scene().active_shape()
object01.remove()
前もって、変数にしておけば、自分のコード内で、作ったものを管理できる。
この変数名を使えば、いちいち選択しなくても、そのオブジェクトに変更を施せる。
例えば、
- 透明度をどんどん上げながら
- レンダリング
- 保存
する時に、a.で処理するオブジェクトを指定できる。
もはや、remove()は関係ないが、
import os
a = xshade.scene().active_shape()
for i in range(10):
#拡散反射色毎回同じなら、ループに入れる必要ないが。
a.surface.diffuse = 1.0
a.surface.diffuse_color = (0,0,0)
#透明
a.surface.transparency = float(i)/10.0
a.surface.transparency_color = (0,1,0)
xshade.scene().rendering.render()
file_path = os.environ["HOMEPATH"] +"\\%05.f.png"%i
xshade.scene().rendering.image.save(file_path)
a = xshade.scene().active_shape()となっているので、現在選択中のshapeが変わったら、そちらの方が処理されるのではという心配はいらない。
きちんと、a = xshade.scene().active_shape()を処理した時点で、active_shape()だったものが処理される。
これなら、一旦宣言してしまえば、選択状態なんか気にしなくてもいつでも呼び出して使える。
removeについて、書こうとしているのに、removeを使っていない。
あれ、このオブジェクト、何て名前だったっけ?→print globals()
テキストエディタでファイルを編集して、それを読み込んで実行する時は、こんな事は、起こりえないけど、
インタプリタに、直接書き込んだりしていると…
どこかで書き間違えてエラー起こる。
→ 同じ処理を避けるために、前に書いた分を消す。
などして、自分で宣言した変数名を忘れてしまう事があるかもしれない。
print globals()
で、定義した変数名一覧が見れた。
(自分だけではないと思いますが。)
(一応、テキストエディタで書いて、保存してから、やっていますが。)
オブジェクトに名前を付けて、削除。
これは、GUIのブラウザから見れる名前なので、忘れても心配がいらない。
xshade.scene().active_shape().name="オブジェクト"
xshade.scene().get_shape_by_name('オブジェクト',True).remove()
インタプリタならでは。
「自分で宣言した変数名を忘れて大変」とか、インタプリタ言語ならではだ。
コンパイルするようなやつは、忘れたら、書いてあるから、思い出すまで読めばいいわけだし。
(書いてあるはずなのに…書いてあると思ってたのに…書いてない事も結構あるけど…バージョン管理の問題なのか、消しちゃったのかなんなのか。)