ON-BLOG

CGのこと、あれこれ書いてます。

NameSpaceをすべて削除

リグ組んでたり、アニメーションを読み込みしてたりすると
偶にネームスペースが邪魔になることがある。
その都度一々、ネームスペースエディタを開いていたら
面倒なので、マクロを作りました。
※家用。

# -*- encoding: utf-8 -*-
import maya.cmds as cmds
def main():
    NameSpace = cmds.namespaceInfo(recurse=1,listOnlyNamespaces=1)
    NameSpace.remove(u'UI')
    NameSpace.remove(u'shared')
    if len(NameSpace) > 0:
        for i in NameSpace:
            cmds.namespace(mergeNamespaceWithRoot = True , removeNamespace = i)
        cmds.headsUpMessage( u'NameSpaceを削除しました', verticalOffset=20 )
    else:
        print "NotNameSpace"


今後は指定したやつだけ残す機能とか付けたい。

以上です。

カメラを作成

スクリプトからカメラを作るコード。
これ自体はなんら意味のないものですが
これに色々載せると、自由なカメラリグに。

というか、Aimカメラの作り方がわからなかったので
それを実行しただけですが…


def Normal_Camera(self):
    cameraName = cmds.camera()
    cmds.select(cameraName[0])
    Sel = cmds.ls(sl=True)[0]
    Camera = cmds.rename(cameraName[0],"Camera")
    cmds.setAttr(Camera + "Shape.horizontalFilmAperture",0.935)
    cmds.setAttr(Camera + "Shape.filmFit",1)
    cmds.setAttr(Camera + "Shape.focalLength",float(55))
    cmds.setAttr(Camera + "Shape.locatorScale",10)
    cmds.setAttr(Camera + ".rotateY", 0)
    cmds.select(cl=True)

def Aim_Camera(self):
    cameraName = cmds.camera()
    cmds.select(cameraName[0])
    Sel = cmds.ls(sl=True)[0]
    Camera = cmds.rename(cameraName[0],"Aim_Camera")
    cmds.setAttr(Camera + "Shape.horizontalFilmAperture",0.935)
    cmds.setAttr(Camera + "Shape.filmFit",1)
    cmds.setAttr(Camera + "Shape.focalLength",float(20))
    cmds.setAttr(Camera + "Shape.locatorScale",10)
    GrpCam = cmds.createNode('lookAt',n="Camera_Set_grp")
    AimLoc = cmds.spaceLocator(n="Aim")[0]
    cmds.setAttr(AimLoc + ".translateZ", -50)

    cmds.parent(Camera,GrpCam)
    cmds.parent(AimLoc,GrpCam)
    cmds.connectAttr(GrpCam + ".distanceBetween", Camera + "Shape.centerOfInterest")
    cmds.connectAttr(AimLoc + ".translateX", GrpCam + ".target[0].targetTranslateX")
    cmds.connectAttr(AimLoc + ".translateY", GrpCam + ".target[0].targetTranslateY")
    cmds.connectAttr(AimLoc + ".translateZ", GrpCam + ".target[0].targetTranslateZ")
    cmds.connectAttr(AimLoc + ".parentMatrix[0]", GrpCam + ".target[0].targetParentMatrix")
    cmds.connectAttr(AimLoc + ".rotatePivot", GrpCam + ".target[0].targetRotatePivot")
    cmds.connectAttr(AimLoc + ".rotatePivotTranslate", GrpCam + ".target[0].targetRotateTranslate")
    cmds.connectAttr(Camera + ".translate", GrpCam + ".constraintTranslate")
    cmds.connectAttr(Camera + ".parentInverseMatrix[0]", GrpCam + ".constraintParentInverseMatrix")
    cmds.connectAttr(Camera + ".rotatePivot", GrpCam + ".constraintRotatePivot")
    cmds.connectAttr(Camera + ".rotatePivotTranslate", GrpCam + ".constraintRotateTranslate")
    cmds.connectAttr(GrpCam + ".constraintRotateX", Camera + ".rotateX")
    cmds.connectAttr(GrpCam + ".constraintRotateY", Camera + ".rotateY")
    cmds.connectAttr(GrpCam + ".constraintRotateZ", Camera + ".rotateZ")

    cmds.setAttr(GrpCam + ".aimVectorZ", -1)
    cmds.setAttr(GrpCam + ".aimVectorX", 0)
    cmds.setAttr(AimLoc + "Shape.localScaleX", 10)
    cmds.setAttr(AimLoc + "Shape.localScaleY", 10)
    cmds.setAttr(AimLoc + "Shape.localScaleZ", 10)
    
Normal_Camera(None)
Aim_Camera(None)


以上。

名前変更

まぁよくあるやつ。
何回書いたことか…

って事で今後ググらないように、雛形をここにメモ。

import os
import glob

#パス指定
path = "D:/demo"
#拡張子FBXだけ取得
files = glob.glob(path + '/*.fbx')

for f in files:
 #例題
    #player_mot_0000.fbx
    #↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
    #enemy_mot_0000.fbx
 #頭6文字を置き換え
    os.rename(f, os.path.join(path, 'enemy' + os.path.basename(f)[6:]))

以上。

animCurveについてメモ

animCurveについてメモ。
いつもいつもあれ?なんだっけ?
ってなるんで、メモ代わりに残こそうかと。

ヘルプを見るとこれだけあります。
animCurve
animCurveTA
animCurveTL
animCurveTT
animCurveTU
animCurveUA
animCurveUL
animCurveUT
animCurveUU


以下が説明。

animCurve・・・・・・・・アニメーションカーブ全部
animCurveTA・・・・・ローテーションのカーブ
animCurveTL・・・・・トランスレーションのカーブ
animCurveTT・・・・・Timeなどのカーブ
animCurveTU・・・・・スケールとビジビリティのカーブ
※頭の【T】は【Time】なので、アニメーションを表す。

animCurveUA・・・・・ドリブンキーのローテーションカーブ
animCurveUL・・・・・ドリブンキーのトランスレーションカーブ
animCurveUT・・・・・ドリブンキーのTimeカーブ
animCurveUU・・・・・ドリブンキーのスケールとビジビリティカーブ
※頭の【U】は【Double】なので許容桁数が多い少数値になり
  MAYAでは、ドリブンキーなどの数値を表す。

ちなみに、【A】はAngle
【L】Distance
【U】Double
【T】Time
になる。



以上メモ。

小物メモ2

続き

選択のコンストレイントを削除するやつ。
ツール作るまではこれで、コンストを削除してました。

import maya.cmds as cmds

def SelAll_Const_Del():
    sel= cmds.ls(sl=True,type="constraint")
    for i in sel:
        cmds.delete(i)


続いて、これは入力した文字数頭から
文字列を削除してます。
あやまって変な名前を頭に付けてしまったときに
一度だけ使った気がします。。。
これが
f:id:tommy_on:20180502225917p:plain
こうなる。
f:id:tommy_on:20180502225934p:plain

# coding: UTF-8
import sys
import maya.cmds as cmds 

err = []

def Renamen(Counts):
    sel = cmds.ls(sl=True,shortNames=True)
    for file in sel:
        RenameSet = file.rsplit('|')[-1]
        Front = RenameSet[:Counts]
        End = RenameSet[Counts:]
        try:
            cmds.rename(file ,End)
        except:
            err.append(file)
    if len(err) > 0 :
        st = u"以下のファイルに同名処理の疑いがある為、スキップしています。\n" + str(err)
        cmds.confirmDialog(message = st  ,b= u"確認")
    else:
        cmds.headsUpMessage( u'作業が終了しました。', verticalOffset=20 )

result = cmds.promptDialog(title=u'分割するカット数を入力ください。',
message=u'分割数(数字以外入れないで下さい)',
text=u"2",
button=['OK', 'Cancel'],
defaultButton='OK',
cancelButton='Cancel',
dismissString='Cancel')
if result == "OK":
    text = cmds.promptDialog(query=True, text=True)
    if text.isdigit():
        Counts = int(text)
        Renamen(Counts)
    else:
        cmds.confirmDialog(message = u"数字を入力してください",b= u"確認")
        print u"キャンセルされました"
else:
    print u"キャンセルされました"

これは選択したアニメーション範囲に
シーンのライムレンジを合わせるスクリプト
今は他のツールに統合してるので使ってない。

import maya.cmds as cmds

Sel = cmds.ls(sl=True)
if len(Sel) > 0:

    cmds.playbackOptions(e=True,ast='-10000')
    cmds.playbackOptions(e=True,min='-10000')
    cmds.playbackOptions(e=True,aet='10000')
    cmds.playbackOptions(e=True,max='10000')
    In = cmds.findKeyframe(timeSlider=True, which='first') 
    Out = cmds.findKeyframe(timeSlider=True, which='last') 
    
    cmds.playbackOptions(e=True,ast=In)
    cmds.playbackOptions(e=True,min=In)
    cmds.playbackOptions(e=True,aet=Out)
    cmds.playbackOptions(e=True,max=Out)

とりあえずこれで最後に
こいつはなぜ作ったのか?まったく覚えてないんですが
あったんでとりあえずアップ。
骨選んで実行すると
同じような階層でロケーターができます。
これが
f:id:tommy_on:20180502225712p:plain
こうなります。
f:id:tommy_on:20180502225729p:plain

# -*- coding: utf-8 -*-
"""
骨選んで実行すると、その階層と同じロケーターが作成され
選択された骨は、こちらに回転コンストレインがかけられる。
"""

import maya.cmds as cmds

Sel = cmds.ls(sl=True)

if len(Sel) > 0:
    RigGrp = cmds.group(n="Rigging",empty=True)
    index = 0
    Hako = []
    Oya_Loc = ""
    for i in Sel:
        Loc = cmds.spaceLocator(n="Tail_Transfer_" + str(index))
        PosC = cmds.pointConstraint(i,Loc)
        OriC = cmds.orientConstraint(i,Loc)
        cmds.delete(PosC,OriC)
        if index == 0:
            Oya_Loc = Loc[0]
        index = index + 1
        Hako.append(Loc)
    Hako.reverse()
    for p in range(len(Hako)):
        try:
            cmds.parent(Hako[p],Hako[p+1])
            cmds.select(Hako[p+1])
        except:
            print "NG"
    cmds.parent(Oya_Loc,RigGrp)
    cmds.select(Oya_Loc,hierarchy=True)
    SelLoc = cmds.ls(sl=True,tr=True)
    for L in range(len(SelLoc)):
        print SelLoc[L]
        print Sel[L]
        OriC = cmds.orientConstraint(SelLoc[L],Sel[L])
else:
    print "NG"

ほかにもあるけど、ちょいちょい仕事の内容も含みながら書いてたりするので
この程度で…

どうせまた増えるし…

小物メモ

MacBookAirのデスクトップに放置してた、スクリプトをメモ代わりにここに残そうかと。

●SpeedChange
FPSを簡単に変えるスクリプト
モーション作成時に、一々変更するのが
面倒だったので作ったと思います。
f:id:tommy_on:20180501231151p:plain

# -*- encoding: utf-8 -*-
import maya.cmds as cmds
import maya.mel as mel

def SetTime(item):
    print item
    if item == "realtime":
        cmds.playbackOptions( edit=True , ps=1.0)
    elif item == "3x":
        cmds.playbackOptions( edit=True , ps=3.0)
    elif item == "2x":
        cmds.playbackOptions( edit=True , ps=2.0)
    elif item == "1/2x":
        cmds.playbackOptions( edit=True , ps=0.5)
    elif item == "1/3x":
        cmds.playbackOptions( edit=True , ps=0.3)
    elif item == "1/4x":
        cmds.playbackOptions( edit=True , ps=0.2)
    elif item == "1/5x":
        cmds.playbackOptions( edit=True , ps=0.1)
             
def main():
    ChangeFPS_window = "ChangeFPS"
    WindowWidth_Size = 170
    WindowHight_Size = 60

    if cmds.window(ChangeFPS_window,exists=True):
        cmds.deleteUI(ChangeFPS_window,window=True)
    MakeWindow = cmds.window(ChangeFPS_window,title=ChangeFPS_window,sizeable=False,mxb=False,mnb=False,wh=[WindowWidth_Size,WindowHight_Size])

    cmds.columnLayout(w=WindowWidth_Size)
    cmds.text(l=u"選択した設定に、再生スピードを変更します。")
    cmds.optionMenu( label='Speed', changeCommand=SetTime)
    cmds.menuItem( label='realtime' )
    cmds.menuItem( label='3x' )
    cmds.menuItem( label='2x' )
    cmds.menuItem( label='1/2x' )
    cmds.menuItem( label='1/3x' )
    cmds.menuItem( label='1/4x' )
    cmds.menuItem( label='1/5x' )
    cmds.showWindow()
main()

●ネームスペース取得Tips
これで取得できるのが知らなかったのでメモ

# -*- encoding: utf-8 -*-
import maya.cmds as cmds
NameSpace = cmds.namespaceInfo(recurse=1,listOnlyNamespaces=1)
NameSpace.remove(u'UI')
NameSpace.remove(u'shared')
print NameSpace


●スキンクラスターあれこれ取得
これはかなり昔のやつ。
一応メモ。

# -*- coding: utf-8 -*-
from maya import cmds
selection = cmds.ls(sl=True)
shapes = cmds.listRelatives(selection[0],s=True,pa=True,type='mesh')

if not shapes:
	cmds.error('Node has no shape')
else:
	srcSkinCluster = cmds.listConnections(shapes[0]+'.inMesh',s=True,d=False)
	#スキンクラスター
	srcSkinCluster = srcSkinCluster[0]
	#スキング方法
	skinningMethod = cmds.getAttr(srcSkinCluster+'.skm')
	#ドロップオフ率
	dropoffRate = cmds.getAttr(srcSkinCluster+'.dr')
	#最大インフルエンス数の保持
	maintrainMaxInfluences = cmds.getAttr(srcSkinCluster+'.mmi')
	#最大インフルエンス数
	maxInfluences = cmds.getAttr(srcSkinCluster+'.mi')
	#ジョイントとジオメトリのポイントの間の最短距離
	bindMethod = cmds.getAttr(srcSkinCluster+'.bm')
	#ウェイトの正規化
	normalizeWeight = cmds.getAttr(srcSkinCluster+'.nw')
	#インフルエンスオブジェクト
	influences = cmds.skinCluster(srcSkinCluster,q=True,inf=True)
	print dropoffRate

まだあるけど、一旦これだけアップ。
以上。

色々バックアップするツール

ちょいと用があり、昨日書いたスクリプトです。
こんなやつです。
f:id:tommy_on:20180112001639p:plain

シーンファイル、Xgenファイルをテキストベースのメモを残してバックアップするツールです。
Xgenはお知り合いからの要望で含めてます。
処理は簡易です。
セーブして、そのファイルをコピーしているだけです。
コードはこんな感じ。
インポート周りがすごく汚いです…

# -*- coding: utf-8 -*-
#######################################
import maya.cmds as cmds
import sys
import os
import json
import codecs
from functools import partial
import os.path
import shutil
import datetime
import xgenm as xg
#######################################


class Tt_FileBackUp:

    ExFrameLayout = ""
    Tt_windowName = "Tt_FileBackUp"
    In = cmds.playbackOptions(q=True,min=True)
    Out = cmds.playbackOptions(q=True,max=True)
    FilesPath = ""
    OutDirValue = ""
    OutDirButton = ""
    InDirValue = ""

    @classmethod
    def main(self,*args):

        if cmds.window(self.Tt_windowName ,exists=True):
            cmds.deleteUI(self.Tt_windowName ,window=True)

        MainWindow = cmds.window(self.Tt_windowName,t=self.Tt_windowName,w=450,resizeToFitChildren=True)
        cmds.columnLayout()
        self.ExFrameLayout = cmds.frameLayout(l="Export",backgroundColor=[0.8,0.2,0.3],w=450)
        cmds.rowLayout(nc=1)
        cmds.text(l=u"  ■書き出し")
        cmds.setParent("..")

        cmds.rowLayout(nc=3)
        self.OutDirValue = cmds.textField(w=410)
        self.Tt_Path = cmds.workspace(q=True,rootDirectory=True)

        cmds.textField( self.OutDirValue, edit=True,text=self.Tt_Path,enable=False)
        self.OutDirButton = cmds.button(l="...",w=30,enable=False)
        cmds.setParent("..")
        
        cmds.rowLayout(nc=3)
        self.CheckScene = cmds.checkBox(l=u"Sceneファイルも書き出す",v=True)
        self.CheckMemo = cmds.checkBox(l=u"メモファイルも書き出す",v=True,cc=self.ChangeBox)
        self.CheckXGen = cmds.checkBox(l=u"XGenファイルも書き出す",v=True)
        cmds.setParent("..")
        
        cmds.rowLayout(nc=1)
        cmds.text(l=u"  ■メモ (こちらに記載して下さい。)")
        cmds.setParent("..")
        
        cmds.rowLayout(nc=1)
        self.TectBox = cmds.scrollField( editable=True, wordWrap=True, text=u'',h=90,w=440 )
        cmds.setParent("..")
        
        cmds.rowLayout(nc=1)
        cmds.button(l="Export!!",w=440,h=40,backgroundColor=[0.8,0.2,0.3],c=self.BackUPPPPPP)
        cmds.setParent("..")

        cmds.showWindow(MainWindow)
        
    @classmethod
    def ChangeBox(self,*args):
        Value = cmds.checkBox(self.CheckMemo,q=True,v=True)
        if Value:
            cmds.scrollField(self.TectBox, e=True,enable=True)
        else:
            cmds.scrollField(self.TectBox, e=True,enable=False)

    @classmethod
    def BackUPPPPPP(self,*args):
        Flag = cmds.checkBox(self.CheckScene,q=True,v=True)
        FlagXgen = cmds.checkBox(self.CheckXGen,q=True,v=True)
        day = datetime.datetime.now()
        Time = day.strftime("%m-%d_%Hh%Mm%Ss")
        Scene_Name = cmds.file( query=True, sn=True).rpartition( "/" )[0] 
        Scene_Name_Only = cmds.file( query=True, sn=True , shn=True).partition( "." )[0]
        Scene_Exten = cmds.file( query=True, sn=True , shn=True).partition( "." )[-1]
            
        Path = Scene_Name + "/versionFolder/"
        if not os.path.exists(Path): 
            os.makedirs(Path)
        Path2 = Path + "/" + Time + "/"
        if not os.path.exists(Path2): 
            os.makedirs(Path2)

        if Flag:
            cmds.file(save=True, force=True)            
            Rename = str(Path2)+str(Scene_Name_Only)+"_"+str(Time)+"."+Scene_Exten
            Scene_Dir = cmds.file( query=True, sn=True)
            shutil.copyfile(Scene_Dir, Rename)
        
        if FlagXgen:
            Scene_Name = cmds.file( query=True, sn=True).rpartition( "/" )[0]
            XGenPath = Scene_Name.rpartition( "/" )[0] + "/xgen/"

            if not os.path.exists(XGenPath): 
                os.makedirs(XGenPath)

            Sel = cmds.ls(sl=True)[0]
            try:
                xg.exportPalette(str(Sel), str(XGenPath) + "Collection.xgen")
                pass
            except:
                print "NG"
            RenameXgen = str(Path2)+str(Scene_Name_Only)+"_"+str(Time)+".xgen"
            shutil.copyfile(str(XGenPath) + "Collection.xgen", RenameXgen)
        
        FlagMemo = cmds.checkBox(self.CheckMemo,q=True,v=True)
        if FlagMemo:
            f = codecs.open(Path2 + Scene_Name_Only + "_" + Time +".txt",'w','utf-8')
            textVal = cmds.scrollField(self.TectBox,q=True,text=True)
            WriteText = textVal.splitlines()
            print "Export Files!!"
            for i in WriteText:
                f.write(i)
                f.write("\r\n")
            f.close()
        print "OK"
        cmds.headsUpMessage( u'書き出しが完了しました!',time=3.0)
F_BackUp = Tt_FileBackUp
F_BackUp.main()

こんな挙動です。

file_backup from tommy_on on Vimeo.


今後はエクセルだったりに記載できるように、SVNにもあげれるようにしたいところ。
※仕事で使うなら。

以上です。