import copy #ソフトムーブ #アルゴリズム改良(2010.02.01) #選択している頂点の第一接続点、第二接続点、第三接続点・・・・が #やわらかく移動します #移動先と移動量の指標は、「最初に選択した頂点」と「カーソルのクリック位置」で決定します #上位パートに変換がかかっていたり、ローカル座標モードのときは結果が不正になります #パラメーター #type・・・・減衰タイプ  「直線(0)」「カーブ(1)」「カスタム(2)」 #val1・・・・接続点ごとにこの値分変化していく 「直線」の場合は1からこの値(*接続番目)を減らしたものをかけていき、「カーブ」の場合はこの値をかけていく。「カスタム」は別パラメーターで制御 #area・・・・何番目の接続点まで影響を与えるか(0が第一接続まで 1が第二接続まで 2が第三接続まで・・・・・・・・) #c1val・・・・カスタムの場合の一次接続点の変化率(元の移動量にこの値をかける) #c2val・・・・カスタムの場合の二次接続点の変化率(元の移動量にこの値をかける) #c3val・・・・カスタムの場合の三次接続点の変化率(元の移動量にこの値をかける) #c4val・・・・カスタムの場合の四次接続点の変化率(元の移動量にこの値をかける) #c5val・・・・カスタムの場合の五次接続点の変化率(元の移動量にこの値をかける) #c6val・・・・カスタムの場合の六次接続点の変化率(元の移動量にこの値をかける) #c7val・・・・カスタムの場合の七次接続点の変化率(元の移動量にこの値をかける) #kizyun・・・基準点の選択 0が最初に選択した頂点 1が最後に選択した頂点 #seigen・・・弟階層に同一の形状があり頂点が選択されている場合、弟階層の選択頂点のみ移動するかどうか #xon・・・・0のときはx座標は移動しない #yon・・・・0のときはy座標は移動しない #zon・・・・0のときはz座標は移動しない #動作条件 #選択形状がポリゴンメッシュ #編集モードに入っている #頂点編集モード #頂点が1個以上選択されている def erase_same_num(list1): #リスト内に同じ値が重複する場合は一つに減らす関数 例[1,1,1,3,3,4]→[1,3,4] #呼び出す時はlist=erase_same_num(list)ではなく、erase_same_num(list)で良い list1.sort() nagasa=len(list1) if nagasa>1: kesu=[] for i in range(nagasa-1): if list1[i]==list1[i+1]: kesu.append(list1[i]) kesukaisuu=len(kesu) if kesukaisuu>0: for i in kesu: list1.remove(i) def return_pointlist(pointnum,vvlist): #その点と接続されている頂点の頂点番号をリストで返す(引数 頂点番号) return vvlist[pointnum] def sort_point_by_active_order(pointlist): #頂点の選択番号(active_order)順にリストの頂点番号をソートして頂点リストを返す #ソート templist=[] for i in pointlist: templist.append(i) newlist=[] while(len(newlist)0:dousasuru=1 #弟階層に同じ形状があり、頂点が選択されていないかどうか(弟形状で移動する頂点を制限) if dousasuru==1: broari=0 if xshade.scene().active_shape().has_bro==True: anipnum=xshade.scene().active_shape().total_number_of_control_points xshade.scene().select_brother() bropnum=xshade.scene().active_shape().total_number_of_control_points if anipnum==bropnum: broactiveplist=[] for i in range(xshade.scene().active_shape().total_number_of_control_points): if xshade.scene().active_shape().vertex(i).active==True: broactiveplist.append(i) if len(broactiveplist)>0:broari=1 xshade.scene().select_sister() if dousasuru==1: #選択番号が低い順に並べ替える activeplist=sort_point_by_active_order(activeplist) cursorpos=xshade.scene().cursor_position #カーソル位置 #ここに初期値 kizyun=0 renzoku=1 type=0 val1=0.3 area=4 c1val=0.9 c2val=0.8 c3val=0.7 c4val=0.6 c5val=0.5 c6val=0.4 c7val=0.3 c8val=0.2 c9val=0.1 c10val=0.0 xon=1 yon=1 zon=1 seigen=0 #基準点の選択 kizyun=0 dialog33=xshade.create_dialog() idgx=dialog33.append_radio_button('基準点/最初に選択した頂点/最後に選択に追加した頂点') dialog33.set_value(idgx,kizyun) kekka33=dialog33.ask('基準点の選択') if kekka33==False:renzoku=0 else: kizyun=dialog33.get_value(idgx) if kizyun==0: startp=activeplist[0] #最初に選択した頂点 else: startp=activeplist[len(activeplist)-1] #最後に選択に追加した頂点 startppos=xshade.scene().active_shape().vertex(startp).position #基準点の頂点の位置 while(renzoku==1): #ダイアログを表示 dialog=xshade.create_dialog() idx1=dialog.append_radio_button('タイプ/減算「1-(値xn)」/乗算「1x(値のn乗)」/二乗減算「1−{(値xn)の二乗}」/カスタム') idx2=dialog.append_float('値') idx3=dialog.append_selection('範囲/1次接続点まで/2次接続点まで/3次接続点まで/4次接続点まで/5次接続点まで/6次接続点まで/7次接続点まで/8次接続点まで/9次接続点まで/10次接続点まで') dialog.begin_group() dialog.begin_box(False) idx11=dialog.append_bool('x座標移動') idx12=dialog.append_bool('y座標移動') idx13=dialog.append_bool('z座標移動') dialog.end_box() dialog.end_group() if broari==1: idx4=dialog.append_bool('弟形状で選択した頂点のみ移動する') dialog.begin_group('カスタムの場合') idxc1=dialog.append_float('1次接続点適用率') idxc2=dialog.append_float('2次接続点適用率') idxc3=dialog.append_float('3次接続点適用率') idxc4=dialog.append_float('4次接続点適用率') idxc5=dialog.append_float('5次接続点適用率') idxc6=dialog.append_float('6次接続点適用率') idxc7=dialog.append_float('7次接続点適用率') idxc8=dialog.append_float('8次接続点適用率') idxc9=dialog.append_float('9次接続点適用率') idxc10=dialog.append_float('10次接続点適用率') dialog.end_group() dialog.set_value(idx1,type) dialog.set_value(idx2,val1) dialog.set_value(idx3,area) if broari==1: dialog.set_value(idx4,seigen) dialog.set_value(idx11,xon) dialog.set_value(idx12,yon) dialog.set_value(idx13,zon) dialog.set_value(idxc1,c1val) dialog.set_value(idxc2,c2val) dialog.set_value(idxc3,c3val) dialog.set_value(idxc4,c4val) dialog.set_value(idxc5,c5val) dialog.set_value(idxc6,c6val) dialog.set_value(idxc7,c7val) dialog.set_value(idxc8,c8val) dialog.set_value(idxc9,c9val) dialog.set_value(idxc10,c10val) kekka=dialog.ask('ソフトムーブ') if kekka==False: renzoku=0 if kekka==True: type=dialog.get_value(idx1) val1=dialog.get_value(idx2) if (type==1 or type==2) and val1<0: val1=val1*(-1) area=dialog.get_value(idx3) if broari==1: seigen=dialog.get_value(idx4) xon=dialog.get_value(idx11) yon=dialog.get_value(idx12) zon=dialog.get_value(idx13) c1val=dialog.get_value(idxc1) c2val=dialog.get_value(idxc2) c3val=dialog.get_value(idxc3) c4val=dialog.get_value(idxc4) c5val=dialog.get_value(idxc5) c6val=dialog.get_value(idxc6) c7val=dialog.get_value(idxc7) c8val=dialog.get_value(idxc8) c9val=dialog.get_value(idxc9) c10val=dialog.get_value(idxc10) xscene=xshade.scene() ashape=xshade.scene().active_shape() #元の形状をクリップボードにコピー xshade.scene().active_shape().copy() xshade.scene().enter_modify_mode() vvlist=[]#頂点の隣接頂点リストを頂点番号順に格納したもの for i in range(ashape.total_number_of_control_points): vvlist.append([]) for i in range(ashape.number_of_edges): vv0=ashape.edge(i).v0 vv1=ashape.edge(i).v1 tempv=vvlist[vv0] tempv.append(vv1) vvlist[vv0]=tempv tempv=vvlist[vv1] tempv.append(vv0) vvlist[vv1]=tempv #頂点の数だけ「−1」の値を入れたリストを作成 #(ここに−1が入れられている頂点は、まだどの頂点群にも属していない) lista=[] for i in range(xshade.scene().active_shape().total_number_of_control_points): lista.append(-1) #最初に選択している頂点は対応するlistaで0の値を入れる for i in activeplist: lista[i]=0 #一次接続点を検査するとともに、listaで対応する位置に1を入れていく list1=[] for i in activeplist: templist=vvlist[i] for g in templist: if lista[g]==-1: list1.append(g) lista[g]=1 erase_same_num(list1) #二次接続点を検査するとともに、listaで対応する位置に2を入れていく if area>0: list2=[] for i in list1: templist=vvlist[i] for g in templist: if lista[g]==-1: list2.append(g) lista[g]=2 erase_same_num(list2) #三次接続点を検査するとともに、listaで対応する位置に3を入れていく if area>1: list3=[] for i in list2: templist=vvlist[i] for g in templist: if lista[g]==-1: list3.append(g) lista[g]=3 erase_same_num(list3) #四次接続点を検査するとともに、listaで対応する位置に4を入れていく if area>2: list4=[] for i in list3: templist=vvlist[i] for g in templist: if lista[g]==-1: list4.append(g) lista[g]=4 erase_same_num(list4) #五次接続点を検査するとともに、listaで対応する位置に5を入れていく if area>3: list5=[] for i in list4: templist=vvlist[i] for g in templist: if lista[g]==-1: list5.append(g) lista[g]=5 erase_same_num(list5) #六次接続点を検査するとともに、listaで対応する位置に6を入れていく if area>4: list6=[] for i in list5: templist=vvlist[i] for g in templist: if lista[g]==-1: list6.append(g) lista[g]=6 erase_same_num(list6) #七次接続点を検査するとともに、listaで対応する位置に7を入れていく if area>5: list7=[] for i in list6: templist=vvlist[i] for g in templist: if lista[g]==-1: list7.append(g) lista[g]=7 erase_same_num(list7) #八次接続点を検査するとともに、listaで対応する位置に7を入れていく if area>6: list8=[] for i in list7: templist=vvlist[i] for g in templist: if lista[g]==-1: list8.append(g) lista[g]=8 erase_same_num(list8) #9次接続点を検査するとともに、listaで対応する位置に7を入れていく if area>7: list9=[] for i in list8: templist=vvlist[i] for g in templist: if lista[g]==-1: list9.append(g) lista[g]=9 erase_same_num(list9) #10次接続点を検査するとともに、listaで対応する位置に7を入れていく if area>8: list10=[] for i in list9: templist=vvlist[i] for g in templist: if lista[g]==-1: list10.append(g) lista[g]=10 erase_same_num(list10) cactiveplist=copy.copy(activeplist) #「弟形状で選択した頂点のみ移動する」がONの場合、ここで最初に選択した頂点とlist1から7までの頂点で不要な点を削除する if seigen==1: nlist=[] for i in cactiveplist: for g in broactiveplist: if i==g: nlist.append(i) break cactiveplist=nlist nlist=[] for i in list1: for g in broactiveplist: if i==g: nlist.append(i) break list1=nlist nlist=[] if area>0: for i in list2: for g in broactiveplist: if i==g: nlist.append(i) break list2=nlist nlist=[] if area>1: for i in list3: for g in broactiveplist: if i==g: nlist.append(i) break list3=nlist nlist=[] if area>2: for i in list4: for g in broactiveplist: if i==g: nlist.append(i) break list4=nlist nlist=[] if area>3: for i in list5: for g in broactiveplist: if i==g: nlist.append(i) break list5=nlist nlist=[] if area>4: for i in list6: for g in broactiveplist: if i==g: nlist.append(i) break list6=nlist nlist=[] if area>5: for i in list7: for g in broactiveplist: if i==g: nlist.append(i) break list7=nlist nlist=[] if area>6: for i in list8: for g in broactiveplist: if i==g: nlist.append(i) break list8=nlist nlist=[] if area>7: for i in list9: for g in broactiveplist: if i==g: nlist.append(i) break list9=nlist nlist=[] if area>8: for i in list10: for g in broactiveplist: if i==g: nlist.append(i) break list10=nlist #頂点を移動していく #移動ベクトル vec=[cursorpos[0]-startppos[0],cursorpos[1]-startppos[1],cursorpos[2]-startppos[2]] if xon==0:vec[0]=0 if yon==0:vec[1]=0 if zon==0:vec[2]=0 #最初に選択していた頂点を移動(cactiveplist) for i in cactiveplist: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0],tempos[1]+vec[1],tempos[2]+vec[2]] #一次接続点の頂点を移動 if type==0: temval=1-val1 if temval<0:temval=0 if type==1: temval=val1 if type==2: temval=1-(val1)**2 if temval<0:temval=0 if type==3: temval=c1val for i in list1: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #二次接続点の頂点を移動 if area>0: if type==0: temval=1-(val1*2) if temval<0:temval=0 if type==1: temval=val1**2 if type==2: temval=1-(val1*2)**2 if temval<0:temval=0 if type==3: temval=c2val for i in list2: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #三次接続点の頂点を移動 if area>1: if type==0: temval=1-(val1*3) if temval<0:temval=0 if type==1: temval=val1**3 if type==2: temval=1-(val1*3)**2 if temval<0:temval=0 if type==3: temval=c3val for i in list3: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #四次接続点の頂点を移動 if area>2: if type==0: temval=1-(val1*4) if temval<0:temval=0 if type==1: temval=val1**4 if type==2: temval=1-(val1*4)**2 if temval<0:temval=0 if type==3: temval=c4val for i in list4: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #五次接続点の頂点を移動 if area>3: if type==0: temval=1-(val1*5) if temval<0:temval=0 if type==1: temval=val1**5 if type==2: temval=1-(val1*5)**2 if temval<0:temval=0 if type==3: temval=c5val for i in list5: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #六次接続点の頂点を移動 if area>4: if type==0: temval=1-(val1*6) if temval<0:temval=0 if type==1: temval=val1**6 if type==2: temval=1-(val1*6)**2 if temval<0:temval=0 if type==3: temval=c6val for i in list6: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #七次接続点の頂点を移動 if area>5: if type==0: temval=1-(val1*7) if temval<0:temval=0 if type==1: temval=val1**7 if type==2: temval=1-(val1*7)**2 if temval<0:temval=0 if type==3: temval=c7val for i in list7: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #八次接続点の頂点を移動 if area>6: if type==0: temval=1-(val1*8) if temval<0:temval=0 if type==1: temval=val1**8 if type==2: temval=1-(val1*8)**2 if temval<0:temval=0 if type==3: temval=c8val for i in list8: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #九次接続点の頂点を移動 if area>7: if type==0: temval=1-(val1*9) if temval<0:temval=0 if type==1: temval=val1**9 if type==2: temval=1-(val1*9)**2 if temval<0:temval=0 if type==3: temval=c9val for i in list9: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #十次接続点の頂点を移動 if area>8: if type==0: temval=1-(val1*10) if temval<0:temval=0 if type==1: temval=val1**10 if type==2: temval=1-(val1*10)**2 if temval<0:temval=0 if type==3: temval=c10val for i in list10: tempos=xshade.scene().active_shape().vertex(i).position xshade.scene().active_shape().vertex(i).position=[tempos[0]+vec[0]*temval,tempos[1]+vec[1]*temval,tempos[2]+vec[2]*temval] #元に戻す? dialog=xshade.create_dialog() idx3=dialog.append_push_button('結果を確定する場合はokを') idx4=dialog.append_push_button('取り消す場合はcancelを押してください') kekka2=dialog.ask('ソフトムーブ') #キャンセルなら形状を削除してクリップボードの形状を元に戻す #さらに頂点の選択状態も元に戻す? if kekka2==False: idou1=0 if xshade.scene().active_shape().has_sis==True: idou1=1 xshade.scene().paste() xshade.scene().select_sister(1) xshade.scene().clear() if idou1==1: xshade.scene().select_brother() xshade.scene().enter_modify_mode() for i in activeplist: xshade.scene().active_shape().vertex(i).active=True #選択番号が変更されているので、入れなおし for i in range(len(activeplist)): xshade.scene().active_shape().vertex(activeplist[i]).active_order=i+1 if kekka2==True: renzoku=0 #戻す終わり