« C4D Python R13 テスト:テキストファイルを試行錯誤で読み込んでみた… | トップページ | C4D Python R13 テスト:スクリプトでモーダルダイアログをなんとなく使ってみる… »

C4D Python R13 テスト:クローナーで複製したオブジェクトをブールで合体…

C4Dフォーラム「3個以上のオブジェクトを一括でブールする方法」を読んで…

https://www.tmsmedia.co.jp/phpbb/viewtopic.php?f=4&t=137&sid=a06851dc958406beaa314b7c3733c3b9

クローナーで複製された全てのオブジェクトをブール「AとBを合体」で1個にしてみた…

クローナーで複製されるオブジェクトは、閉じたオブジェクトである事が前提ね…

Clonerboolunion_02

まずは…

クローナーを編集可能にします。

Clonerboolunion_03

編集可能にすると、複製されたオブジェクトが実体化されます。
グループ内の先頭2つにブールを適用します。

Clonerboolunion_04

ブールの設定は…
ブールタイプ:AとBを合体
高品質:On
一体化:On
交差エッジをシャープにする:On

Clonerboolunion_05

このブールを編集可能にします。

Clonerboolunion_03

ポリゴンオブジェクトになります。

Clonerboolunion_06

同じように、このブールをしたオブジェクトと次のオブジェクトをブールします。

Clonerboolunion_07

この処理をグループ内のオブジェクトが無くなるまで繰り返します。
最後には、下の様な…
ごめん… ポリゴンが分割されて見苦しくて見づらかったので、N-gonを適用してしまいした…

全てブールが完了して合体したオブジェクトのスムースタグの「シャープエッジを使う」をOnにします。

Clonerboolunion_08

では、Pythonスクリプトを書いてみよう。
最後のN-gonはしませんけどね…

選択されたオブジェクトがクローナーオブジェクトなのか、判定するために…
C4DAtom.GetType()メソッドを使う。
このメソッドの返り値は、オブジェクトを割り当てるときに使う定数なのですが、クローナーオブジェクトを示す定数が見当たりません。

そんな時は、実際にオブジェクトを選択して、次のスクリプトを実行するとわかります。

Python
import c4d


def main():
    print op.GetName(), op.GetType()


if __name__=='__main__':
    main()
クローナー 1018544

この数値:1018544を直接使います。

そう言えば…
グローバル変数:opに代入されているクローナーオブジェクトは、CallCommand()で編集可能にするんだけど…
編集可能処理後の変数:opは、どうなるんだろうね…

Python
import c4d


def main():
    if op.GetType() != 1018544:return

    print op
    c4d.CallCommand(12236) #編集可能にする
    print op


if __name__=='__main__':
    main()
<c4d.BaseObject object called 'クローナー/クローナー' with ID 1018544 at 0x233D4160>
<c4d.BaseObject object called 'クローナー/ヌル' with ID 5140 at 0x233D4160>

処理後、ヌルオブジェクトに変更されているので問題は無いようだ。
ちなみに、ブールオブジェクトも同様でした。

Python
import c4d


def GetBoolObj():
    boolobj = c4d.BaseObject(c4d.Oboole)
    boolobj[c4d.BOOLEOBJECT_TYPE] = c4d.BOOLEOBJECT_TYPE_UNION #AとBを合体
    boolobj[c4d.BOOLEOBJECT_HIGHQUALITY] = True #高品質
    boolobj[c4d.BOOLEOBJECT_SINGLE_OBJECT] = True #一体化
    boolobj[c4d.BOOLEOBJECT_BREAK_CUT_EDGES] = True #交差エッジをシャープにする
    return boolobj


def main():
    #opがクローナーオブジェクトでなければ終了
    try:
        if op.GetType() != 1018544:return
    except:
        return
   
    c4d.CallCommand(12236) #編集可能にする
   
    #子オブジェクトが1個になるまで繰り返す
    while len(op.GetChildren()) > 1:
        #上位2個の子オブジェクトを取得
        child = op.GetChildren()
        ch_1 = child[0]
        ch_2 = child[1]
       
        c4d.CallCommand(12113) #全て選択解除
       
        #ブールを追加し上位2個の子オブジェクトをブールの子オブジェクトに設定
        boolobj = GetBoolObj()
        boolobj.InsertUnder(op)
        boolobj.SetBit(c4d.BIT_AOBJ) #ブールオブジェクトの選択
        ch_1.InsertUnder(boolobj)
        ch_2.InsertUnder(boolobj)
       
        c4d.CallCommand(12236) #編集可能にする
       
        #合体オブジェクトの親オブジェクト(元のブールオブジェクト)を削除するために
        unionobj = boolobj.GetDown()
        unionobj.InsertUnder(op)
        boolobj.Remove()
       
   
    #合体オブジェクトの親オブジェクト(元のクローナオブジェクト)を削除するために
    unionobj = op.GetDown()
    unionobj.InsertAfter(op)
    op.Remove()
   
    #合体オブジェクトの名前の変更
    unionobj[c4d.ID_BASELIST_NAME] = 'union'
   
    #合体オブジェクトのスムーズタグの設定
    Phong_tag = unionobj.GetTag(c4d.Tphong)
    Phong_tag[c4d.PHONGTAG_PHONG_USEEDGES] = True #シャープエッジを使う
   
   
if __name__ == '__main__':
    main()
    c4d.EventAdd()

編集可能にしたクローナーのグループ内にブールオブジェクトを配置して作業をしていますが…
グループの外でも良いよね…

Clonerboolunion_09

その前に、こんなスクリプトを試してみた。

クローナオブジェクトを編集可能にした後の子オブジェクトリストを取得し、その中の2つをブール。
そのブールオブジェクトを編集可能にした後、もう一度取得済みの子オブジェクトリストを表示して確認する。

Python
import c4d


def GetBoolObj():
    boolobj = c4d.BaseObject(c4d.Oboole)
    boolobj[c4d.BOOLEOBJECT_TYPE] = c4d.BOOLEOBJECT_TYPE_UNION #AとBを合体
    boolobj[c4d.BOOLEOBJECT_HIGHQUALITY] = True #高品質
    boolobj[c4d.BOOLEOBJECT_SINGLE_OBJECT] = True #一体化
    boolobj[c4d.BOOLEOBJECT_BREAK_CUT_EDGES] = True #交差エッジをシャープにする
    return boolobj


def main():
    #opがクローナーオブジェクトでなければ終了
    try:
        if op.GetType() != 1018544:return
    except:
        return
   
   
    #クローナーオブジェクトを編集可能にして子オブジェクトを取得
    c4d.CallCommand(12236) #編集可能にする
   
    child = op.GetChildren()
    if len(child) < 2:return
   
   
    c4d.CallCommand(12113) #全て選択解除
   
   
    #取得したクローナーオブジェクトの子オブジェクトを表示してみる。
    print 'before:'
    for obj in child:
        print obj
   
   
    #ブールオブジェクトの設定と編集可能にする
    boolobj = GetBoolObj()
    doc.InsertObject(boolobj, None, None)
    boolobj.SetBit(c4d.BIT_AOBJ) #ブールオブジェクトの選択
    child[0].InsertUnder(boolobj)
    child[1].InsertUnder(boolobj)
   
    c4d.CallCommand(12236) #編集可能にする
   
   
    #ブールオブジェクトを編集可能直後に
    #取得したクローナーオブジェクトの子オブジェクトをもう一度表示してみる。
    print 'after:'
    for obj in child:
        print obj
   
   
if __name__ == '__main__':
    main()
    c4d.EventAdd()

Clonerboolunion_10

befor:
<c4d.BaseObject object called '立方体 0/立方体' with ID 5159 at 0x233D4270>
<c4d.BaseObject object called '立方体 1/立方体' with ID 5159 at 0x233D4280>
<c4d.BaseObject object called '立方体 2/立方体' with ID 5159 at 0x233D4290>
<c4d.BaseObject object called '立方体 3/立方体' with ID 5159 at 0x233D42A0>
<c4d.BaseObject object called '立方体 4/立方体' with ID 5159 at 0x233D42B0>
<c4d.BaseObject object called '立方体 5/立方体' with ID 5159 at 0x233D42C0>
<c4d.BaseObject object called '立方体 6/立方体' with ID 5159 at 0x233D42D0>
<c4d.BaseObject object called '立方体 7/立方体' with ID 5159 at 0x233D42E0>
<c4d.BaseObject object called '立方体 8/立方体' with ID 5159 at 0x233D42F0>
<c4d.BaseObject object called '立方体 9/立方体' with ID 5159 at 0x233D4300>
<c4d.BaseObject object called '立方体 10/立方体' with ID 5159 at 0x233D4310>
<c4d.BaseObject object called '立方体 11/立方体' with ID 5159 at 0x233D4330>
after:
<c4d.BaseObject object called '立方体 0/立方体' with ID 5159 at 0x233D4270>
<c4d.BaseObject object called '立方体 1/立方体' with ID 5159 at 0x233D4280>
<c4d.BaseObject object called '立方体 2/立方体' with ID 5159 at 0x233D4290>
<c4d.BaseObject object called '立方体 3/立方体' with ID 5159 at 0x233D42A0>
<c4d.BaseObject object called '立方体 4/立方体' with ID 5159 at 0x233D42B0>
<c4d.BaseObject object called '立方体 5/立方体' with ID 5159 at 0x233D42C0>
<c4d.BaseObject object called '立方体 6/立方体' with ID 5159 at 0x233D42D0>
<c4d.BaseObject object called '立方体 7/立方体' with ID 5159 at 0x233D42E0>
<c4d.BaseObject object called '立方体 8/立方体' with ID 5159 at 0x233D42F0>
<c4d.BaseObject object called '立方体 9/立方体' with ID 5159 at 0x233D4300>
<c4d.BaseObject object called '立方体 10/立方体' with ID 5159 at 0x233D4310>
<c4d.BaseObject object called '立方体 11/立方体' with ID 5159 at 0x233D4330>

ブールを編集可能にした後もクローナーオブジェクトの子オブジェクトリストは変化しないね。
てっきり、ブールに設定したオブジェクトABは編集可能後、Noneになってしまうと思ったけど…
もしくは、オブジェクトリストの要素が減っていくのかとも思ったけど…
Python側でオブジェクトが参照されている間は、ブールに適用したオブジェクトはブールを編集可能にしても消去されないのか?

これを踏まえてもう一度…
ん?踏まえなくても問題ないかぁ…

Python
import c4d


def
GetBoolObj():
    boolobj = c4d.BaseObject(c4d.Oboole)
    boolobj[c4d.BOOLEOBJECT_TYPE] = c4d.BOOLEOBJECT_TYPE_UNION #AとBを合体
    boolobj[c4d.BOOLEOBJECT_HIGHQUALITY] = True #高品質
    boolobj[c4d.BOOLEOBJECT_SINGLE_OBJECT] = True #一体化
    boolobj[c4d.BOOLEOBJECT_BREAK_CUT_EDGES] = True #交差エッジをシャープにする
    return boolobj


def main():
    #opがクローナーオブジェクトでなければ終了
    try:
        if op.GetType() != 1018544:return
    except:
        return
   
   
    #クローナーオブジェクトを編集可能にして子オブジェクトを取得
    c4d.CallCommand(12236) #編集可能にする
   
    child = op.GetChildren()
    if len(child) < 2:return
   
    c4d.CallCommand(12113) #全て選択解除
    op.Remove()
   
    #クローナーオブジェクトの子オブジェクトを全てブールで合体
    union_obj = child[0]
    for id in xrange(1, len(child)):
        #ブールオブジェクトの設定と編集可能にする
        boolobj = GetBoolObj()
        doc.InsertObject(boolobj, None, None)
        boolobj.SetBit(c4d.BIT_AOBJ) #ブールオブジェクトの選択
        child[id].InsertUnder(boolobj) #ブールのオブジェクトBに設定
        union_obj.InsertUnder(boolobj) #ブールのオブジェクトAに設定
   
        c4d.CallCommand(12236) #編集可能にする
        #合体したオブジェクトの確保
        union_obj = boolobj.GetDown()
        union_obj.Remove() #重要です。
        boolobj.Remove()
   
    #合体されたオブジェクトの設定
    union_obj[c4d.ID_BASELIST_NAME] = 'union'
    doc.InsertObject(union_obj, None, None)
    #スムーズタグの設定
    Phong_tag = union_obj.GetTag(c4d.Tphong)
    Phong_tag[c4d.PHONGTAG_PHONG_USEEDGES] = True #シャープエッジを使う
   
   
if __name__ == '__main__':
    main()
    c4d.EventAdd()

これも、問題なく動作するだろう…

forループの後半にある、

        union_obj.Remove() #重要です。

この処理が無いと、forループの前半にある下記のコードが問題の引き金となります。

        boolobj = GetBoolObj()

ループ2順目で、ブールオブジェクトが新たに生成されると、1順目で使用したboolobjが示しているオブジェクトと共にunion_objが示している合体したオブジェクトが無効になります。

その後の、ブールオブジェクトへの子オブジェクトとしての挿入で、union_objが無効なオブジェクトなのでエラーが起こります。

        union_obj.InsertUnder(boolobj) #ブールのオブジェクトAに設定

ですから、前もってboolobjから親子関係を切り離します。

C.O.F.F.E.E.では、親子関係を付け替えするために必ずRemove()をしなければ、c4dのフリーズや強制終了などが起こりますが、c4d Pythonではまだ経験していません。

この事は、全く問題無いのかは、わかりません。c4d Python SDKでの記載は見当たりませんし…
でも、C.O.F.F.E.E. SDKには記載がありますけどね。

Undo処理をしていないし、CallCommand()を使用しているので、編集メニューの「取り消し」「再実行」は思うように動作しません。

|

« C4D Python R13 テスト:テキストファイルを試行錯誤で読み込んでみた… | トップページ | C4D Python R13 テスト:スクリプトでモーダルダイアログをなんとなく使ってみる… »

コメント

コメントを書く



(ウェブ上には掲載しません)




« C4D Python R13 テスト:テキストファイルを試行錯誤で読み込んでみた… | トップページ | C4D Python R13 テスト:スクリプトでモーダルダイアログをなんとなく使ってみる… »