2016年11月16日水曜日

melメモ:カレントファイルのフルパス・ファイル名・ディレクトリの取得

備忘録的メモです。
proc get_pathList(){
string $fullPath = `file -q -sn`;
string $fileName = `file -q -sn -shn`;
string $dirName = dirname(`file -q -sn`);
print ("<<フルパス>> :: "+$fullPath+"\n");
print ("<<ファイル名>> :: "+$fileName+"\n");
print ("<<ディレクトリ名>> :: "+$dirName+"\n");
}
get_pathList;
view raw get_pathList hosted with ❤ by GitHub

割と忘れて、basenameコマンドやらなんやらを使いがち。。。

2016年11月14日月曜日

blenderスクリプトメモ:ビューポートのカメラ設定を変える

Blenderスクリプトは、カメラ設定をいじるのにも、どこに情報が格納されているのか、探すのに一苦労でした。。

ひとまず、現在のウインドウの、View_3Dパネルを取得できれば、いろいろいじることができそう。

以下ソース
import bpy
areas = bpy.context.screen.areas
for area in areas:
if area.type=='VIEW_3D':
override = bpy.context.copy()
override['area'] = area
#カメラのpersp/orthoを切り替える
bpy.ops.view3d.view_persportho(override)
#カメラをfrontViewに切り替える
bpy.ops.view3d.viewnumpad(override,type = 'FRONT')
spaces = area.spaces
for space in spaces:
v3D=bpy.types.SpaceView3D(space)
#テクスチャ表示
v3D.viewport_shade='TEXTURED'

しかし、ビューにすべてのオブジェクトが入るようにするやり方がわからなかった。
(ショートカットだと、shift+C)
引き続き調査してみます。

blender スクリプトメモ:fileDialogでファイルパスを取得する

Mayaのmelやpythonだと、fileDialogを出すのには全く苦労しませんが、
Blenderはかなり面倒くさかったです。
あちこち調べて、ようやくソースを見つけたので、こちらにメモします。

以下ソース
import bpy
import os
#if chanfe the referense filename, you should change below path.
armatPath='D:/Technical/blender/noBall/blender_RD/scene/bone_set_0928.blend'
#---------------------------------------------------------------
#file Dialog & do SetUp Class
#---------------------------------------------------------------
# ImportHelper is a helper class, defines filename and
# invoke() function which calls the file selector.
from bpy_extras.io_utils import ImportHelper
from bpy.props import StringProperty, BoolProperty, EnumProperty
from bpy.types import Operator
class ImportSomeData(Operator, ImportHelper):
"""This appears in the tooltip of the operator and in the generated docs"""
bl_idname = "import_test.some_data" # important since its how bpy.ops.import_test.some_data is constructed
bl_label = "Import Some Data"
# ImportHelper mixin class uses this
filename_ext = ".fbx"
filter_glob = StringProperty(
default="*.fbx",
options={'HIDDEN'},
)
#files = bpy.props.CollectionProperty(type=ImportFilesCollection)
files = bpy.props.CollectionProperty(type=bpy.types.PropertyGroup)
bpy.types.PropertyGroup
def execute(self, context):
print(len(self.files))
dirname = os.path.dirname(self.filepath)
#fileList=[]
for i, f in enumerate(self.files, 1):
#print("File %i: %s" % (i, f.name))
fbxPath = (os.path.join(dirname, f.name))
fbxPath.replace('\\', '/')
#-------------------------------------------------------------
#Do Proc
print(fbxPath)
#-------------------------------------------------------------
return {'FINISHED'}
# Only needed if you want to add into a dynamic menu
def menu_func_import(self, context):
self.layout.operator(ImportSomeData.bl_idname, text="Text Import Operator")
def register():
bpy.utils.register_class(ImportSomeData)
bpy.types.INFO_MT_file_import.append(menu_func_import)
def unregister():
bpy.utils.unregister_class(ImportSomeData)
bpy.types.INFO_MT_file_import.remove(menu_func_import)
if __name__ == "__main__":
register()
# test call
fileDialog = bpy.ops.import_test.some_data('INVOKE_DEFAULT')

参考:



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

本当は、fileDialogから、単にパスを返すだけのソースにしたかったのですが、解決方法がわからず、fileDialogを呼び出した処理の中に、本処理を書き込む流れになっています。

うーむ。。気持ち悪い。。

というか、たかだかfileDialogだすだけで相当時間を食ってしまった…南無三。


2016年10月20日木曜日

blender::スクリプトで後からActionにgroupを追加し、fcurveを登録する方法

現在、お仕事でBlenderのスクリプトを触っているのですが、まったくMayaのそれとは異質で四苦八苦。。(汗
同じpythonといっても、Blenderのpythonスクリプティングは、完全にオブジェクト指向なので、コマンドを動かして操作するmaya pythonとはまったくハンドリングが違う。
たかだかジョイントツリーを選択するだけで時間がかかる…!

Blender pythonでの操作方法はいくつかわかってきましたが、そのうち一つをこちらでメモを兼ねて公開します。

通常、Blender上でアニメーションを作成すると、ArmatureにActionを登録し、キーフレームを作成すると、Actionデータの中に骨ごとのグループができて、中にfcurveが登録されます。
が、例えば、FBXなどをインポートすると、(出力やインポート方法によって異なるかもですが)、この骨ごとのグループが作成されず、Armature直下にfcurveが登録されます。

これを骨ごとのグループに登録しなおすには、ActionEditor上から手作業でグループを作成…してもよいのですが、面倒。

スクリプトでやると、以下の通りです。

※あらかじめ編集したいArmatureを選択してアクティブにしておくことが前提
※アクティブにするArmatureをスクリプトで指定する方法は、またべつのはなし(笑)

#まず、新規にActionにgroupを追加する。
>>> bpy.context.object.animation_data.action.groups.new('test')
#手動操作時の、infoウインドウにログ表示される「bpy.ops.anim.channels_group(name="testGrp")
」という入力だとなんでか怒られます。おそらく、fcurveがきちんと指定できてないのかも。

#つぎに、アニメーションカーブを取得します。
>>> fcList=bpy.context.object.animation_data.action.fcurves
#カーブごとのグループアトリビュートを指定します。
>>> for fc in fcList:
...     fc.group.name='test'
>>>for fc in fcList:
...     fc.group=bpy.context.object.animation_data.action.groups['test']

※12/1修正:名前指定ではグループに入りませんでした!
※グループオブジェクトを指定する必要があるようです。

…以上!(ジェイソン風味
fcurveごとに登録したいグループを変えるのであれば、fcurveのdata_pathアトリビュートから、UI上に表示されている名前を取得できるので、if文で処理分岐するといいと考えています。

2016年10月13日木曜日

シーン内のすべてのリファレンスノードをインポートする。

メモ代わりに。

proc allImportReference(){
string $refNodeList[] = `ls -rf`;
for($node in $refNodeList){
string $filename = `referenceQuery -f $node`;
if(`file -q -ex $filename`)file -ir $filename;
}
}
リファレンスノードを取得し、ファイルパスを取得、fileコマンドからインポート。

2016年7月23日土曜日

Photoshop JavaScript:レイヤーを別のファイルへ複製する。

業務でPhotoshopのJavaScriptによる自動化を行いました。
その際、「特定レイヤーセットを、別のファイルへ複製する」方法を調べたのですが、なかなかヒットしなかったので、こちらに投稿しておきます。

psObj = open(new File('<コピー先のファイルパス>')); 
refObj = open(new File('<コピー元のファイルパス>')); 
var layObj = refObj.layerSets.getByName("<指定するレイヤーセットの名前>")
layObj.duplicate(psObj)

割と簡単でした。
ちなみに、上記の例では、一番上の階層のレイヤーセットのみを検索します。
その下階層の場合は、指定のlayerSetの中のlayerSetを取得してやる必要があります。

また、この例では、layerSetsのduplicateを行っていますが、通常layerやartLayerからも実行することも可能かも。
(未確認)


2016年7月10日日曜日

pythonでredmineを使う。

オープンソースのプロジェクト管理ソフトウェア、「redmine」ですが、
僕の環境でもredmineを使ったプロジェクト管理を模索しています。

他の会社などの話を様々なセミナーで聞くと、(redmineに限った話ではないですが)様々な環境に合わせたカスタマイズが行われているようです。
Mayaとredmineなどの管理ソフトの連動なども行われていたり。

僕の方でも、redmineをより使いやすくするため、pythonからアクセスする方法を模索してみました。
redmineにはrestAPIでアクセスが可能ですが、pythonでアクセスできれば、
デスクトップToolだけでなく、Mayaとの連動でタスク管理することが可能になってきます。

・python-redmineモジュールを使う。

→これで解決しました(簡単)。 まさにそれ、というモジュールがあったのですね。。
Mayaから実行する場合、MayaのpythonPathが通っているところにモジュールをおいて、importすればOK。
githubにモジュールあるので、ダウンロードして使用できます。

・ssl認証エラーする場合は?

割と壁だったのが、SSL認証。 オレオレ認証かなんかを使っていると、「このサイト信用できまへんで」などと言われてブラウザに怒られます。
python-redmineからアクセスする際も、同じようにエラーが返ってきて、情報が取得できませんでした。
このSSL認証をスキップするには、…

redmine = Redmine('https://redmine.url', requests={'verify': False})

この記述で解決しました。
python-redmineに同梱されている、requestModuleのバージョンによって、
エラー表示が出まくることがありますが、とりあえず実行・情報取得はできました。
エラーを非表示にしたい場合、requestモジュールのバージョンを下げれば解決するそうです。

でもまぁ、値さえ取得できればOKなので、僕は無視してます。

参考URL

http://qiita.com/mima_ita/items/1a939db423d8ee295c85
https://github.com/maxtepkeev/python-redmine/issues/1
https://pypi.python.org/pypi/python-redmine
http://python-redmine.readthedocs.io/resources/issue_category.html#manager

2016年6月19日日曜日

文字分割は、python使ったほうが楽?

pythonでのコーディングは便利でいいですが、やはりmelにはmelの良さがあるし、melのほうが手っ取り早いこともあります。

ただ、melはやっぱりpythonと比べると、文字分割関連がめんどくさい…。

たとえば、文字列…

"aaa/bbb/ccc.bmp"

で、"bbb"を抜き出したい場合、おそらく普通にmelでコーディングすると…


string $temp[] = stringToSTringArray("aaa/bbb/ccc.bmp","/");
string $result = $temp[1] ;

など、stringToStringArrayを使わない場合でも、一度配列に出してから抜き出さないと、だと思います。

今日試してみたのが、pythonを挟む方法です。

string $result = python('aaa/bbb/ccc.bmp'.split('/')[-2]);

…一行で済むというね!


しばらくこちらを試してみようと思います。

pythonソース もう一度importするには??

melのsourdeと違って、pythonの場合、ソースを更新して再度importコマンドを行っても更新されることがありません。
この場合、reload()関数を使うと解決できます。

reload関数()

ほかにも、読み込んだモジュールを削除して再度importする方法を採用している方もいるようです。

.pyファイルの再import

とくにもんだいなければ、reload関数を使うのがよさそうです。

2016年6月17日金曜日

melで、指定パス以下のフォルダ・ファイル階層を取得する。

子供が熱でた~ … ということで、家で作業しております。

Toolを作っている際、データ集合をフォルダ階層に分けて管理・Tool上にそのツリーを表示したい…などというケースは少なくないと思います。

簡単ですが、再帰処理による、「指定パス以下のフォルダ・ファイル階層を取得するmel」を作成しました。
メモ代わりに貼り付けます。
proc string[] GetFileListByPath(string $path){
string $fileList[] = `getFileList -fld $path`;
string $returnList[];
for($data in $fileList){
$data = $path+$data;
if(`filetest -f $data`) $returnList[size($returnList)]=$data;
if(`filetest -d $data`) $returnList = stringArrayCatenate($returnList,`GetFileListByPath($data+"/")`);
}
print $returnList;
return $returnList;
}
treeListerかなんかでフォルダを列挙したいときなんか便利かも。

2016年6月12日日曜日

任意のフォルダのpythonファイルをimport コマンドから持ってくる

Toolのソースを、特定のフォルダの特定階層に整理したいのに、melファイルのsourceコマンドとは違って、pythonのimportコマンドは、あらかじめpythonパスが通っているところしか見てくれない。

そういう場合は、環境変数に書き込むか、一時的リリースのToolなんかだったら、一時的にpythonパスをソースから追加することでインポートが可能です。

サンプルソース;
import sys
def append_PythonPath(PyPath=None):
sys.path.append(PyPath)
append_PythonPath('任意のパス')
これでpythonパスを一時的に追加できるので、この後importコマンドを走らせればいい

2016年2月11日木曜日

選択したキーフレームのリストを取得する

基礎の話なのですが、恥ずかしながらつい先日知ったことを、こちらにも載せておきます。

通常、グラフエディタで選択したキーフレームは、

keyframe -q -sl;

で取得できますが、これは単に、選択したフレーム=time(時間)のリストを返すだけで、
たとえば、複数アトリビュートのキーを同時選択していたとしても、いっしょくたに値が返されます。

アトリビュートとノードのリストは、

keyframe -q -n;

から取得可能ですが、それぞれ別々に実行すると、キーフレームとアトリビュートが関連していません。
このままでは、たとえば「選択したキーすべてにある処理を加える」などの処理がしにくい。。
方法を探していたのですが、何のことはない、「keyframe -q -sl;」の時、そのカーブの名前を指定してあげればよかったのでした。。

つまりは…
string $keyNameList[] = `keyframe -q -n`;
for($keyName in $keyNameList){
print (`keyframe -q -sl $keyName`);
}
…で、各アニメーションカーブごとに、各々選択したキーフレームが取得できました。

…基礎です。(恥


2016年1月5日火曜日

【Maya】 【python】ポリゴンの凹面を判別する。

少し前からですが、アーティストの方から割と要望をいただく件として、
「ポリゴンメッシュの凹面を自動判別する機能」があります。

早めに開発着手したかったのですが、なかなか手が空かず、
時間ばかりいただいてしまいました。。
で、ちょうど年末年始、数学に強い従兄の助言もいただき、
時間のあるこの時期に大体形にしてみたので、こちらでも紹介します。

■どうやって凹凸を判別するか?
 チェックするポリゴンは4頂点の4角形であることが前提です。
 そもそも3角形だったら平面だし。5角形だったらそもそもポリゴン割れし。
 
 で、仕組みはこうです。
 ずばり内積と外積を使います。

 ベクトルの内積と外積を使って、4頂点のうち、
 3頂点の平面から見た残りの1点の位置を判別します。












 








~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
かんたんに外積:
2つのベクトルに垂直なベクトルを算出します。

 

















 
かんたんに内積:
ベクトルAをベクトルBに成分分解したときの、そのベクトルの長さを求めます。



















~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 その手順は…、

 ①3頂点で作る、1点から伸びる2本のベクトルの外積を出して、
 この3角形に垂直なベクトルを算出します。





















 ②残り1頂点で作るベクトルと、①の三角形に垂直なベクトルの内積を求めます。





















 この内積の値が正か負かで、残りの1点の位置が算出できるはずです。

■しかし、ポリゴンのみかたで凹か凸かが変わってしまう。
 この4頂点ですが…

こうみるか




















こうみるかで、凹か凸かが変わってしまいます。




















 要は、どの頂点を判別するのか、準点を定める必要があるわけです。
 ここは、判別の基準をアーティストさんに確認する必要がありますが、、、
 とりあえず、一度Triangulateをかけた時の形状が、凹か凸かを判別するように
 考えることにしました。

 要は、このポリゴンを…





















 Triangulateをかけて…


 この3角形に含まれない頂点…


 つまり、この頂点を判別することにします。


■melに便利なコマンドが
 melにズバリ、内積・外積を算出するコマンドがあるので、これを使うっきゃない。
 
 外積:cross  http://download.autodesk.com/global/docs/maya2014/ja_jp/Commands/cross.html
 内積:dot    http://download.autodesk.com/global/docs/maya2014/ja_jp/Commands/dot.html 

 しかし、頂点計算など、数が多い処理は全てmelで処理するには重たすぎるので、
 基本はすべてpythonで書くことにし、pythonからmelプロシージャを呼び出すようにします。

そんな感じで、ぱっと作ってみました。
※使用方法は、mel文を先に実行しておくか、sourceコマンドで読んでおいた上で
ポリゴンを選択し、python文を実行します。
すると、凹んだ角形のみが選択された状態で終了します。

実際にまだ使っていないので、信頼性は低いですが。
いろいろテストなどして、ブラッシュアップしていこうと思います。
 
以下ソース
//------------------------
//mel部分
//------------------------
global proc float[] ReturnCrosProductList(vector $vec1,vector $vec2){
vector $crossProc = cross($vec1,$vec2);
float $ReturnList[];
$ReturnList[0]=$crossProc.x;
$ReturnList[1]=$crossProc.y;
$ReturnList[2]=$crossProc.z;
return $ReturnList;
}
global proc float ReturnDotProductList(vector $vec1,vector $vec2){
float $ReturnFloat = dot($vec1,$vec2);
return $ReturnFloat;
}
//------------------------
#python部分
#-------------------------
# -*- coding: utf-8 -*-
import maya.cmds as mc
import maya.mel as mel
import math as math
def change_e_to_zero(List=[0,0,0]):
i=0
for num in List:
numstr='%s'%num
if len(numstr.split('e'))>1:
List[i]=0.0
i=i+1
return List
def getRecessedFace():
errorFaceList=[]
faceList=[]
trifaceList=[]
vtxList=[]
triVtxList=[]
chkVtxList=[]
P_org=[]
P_A=[]
P_B=[]
P_C=[]
vec1=[1,1,1]
vec2=[1,1,1]
vec3=[1,1,1]
vecNormal=[1,1,1]
vecCrossProc=[1,1,1]
moreFiveVtxFaceList=[]
faceList=mc.ls(mc.polyListComponentConversion(mc.ls(sl=True),tf=True),fl=True)
#mc.scriptEditorInfo(sr=False)
for face in faceList:
trifaceList[:]=[]
vtxList[:]=[]
chkVtxList[:]=[]
P_org[:]=[]
P_A[:]=[]
P_B[:]=[]
P_C[:]=[]
vtxList = mc.ls(mc.polyListComponentConversion(face,tv=True),fl=True)
try:
if len(vtxList)>4:
print 'This is more 5Vtx Face.'
elif len(vtxList)<4:
print 'This is Triangle Face.'
else:
#get target vtx
mc.select(face)
mc.polyTriangulate(face,ch=False)
trifaceList=mc.ls(sl=True,fl=True)
triVtxList=mc.ls(mc.polyListComponentConversion('%s'%trifaceList[0],tv=True),fl=True)
mc.undo()
mc.select(vtxList)
mc.select(triVtxList,d=True)
chkVtxList=mc.ls(sl=True,fl=True)
mc.select(cl=True)
#get vtx point
P_org=mc.pointPosition('%s'%triVtxList[0])
P_A=mc.pointPosition('%s'%triVtxList[1])
P_B=mc.pointPosition('%s'%triVtxList[2])
P_C=mc.pointPosition('%s'%chkVtxList[0])
#change e to 0
P_org=change_e_to_zero(P_org)
P_A=change_e_to_zero(P_A)
P_B=change_e_to_zero(P_B)
P_C=change_e_to_zero(P_C)
#getVec
vec1 = [P_A[0]-P_org[0],P_A[1]-P_org[1],P_A[2]-P_org[2]]
vec2 = [P_B[0]-P_org[0],P_B[1]-P_org[1],P_B[2]-P_org[2]]
vec3 = [P_C[0]-P_org[0],P_C[1]-P_org[1],P_C[2]-P_org[2]]
vecStr1='<<'+str(vec1[0])+','+str(vec1[1])+','+str(vec1[2])+'>>'
vecStr2='<<'+str(vec2[0])+','+str(vec2[1])+','+str(vec2[2])+'>>'
vecStr3='<<'+str(vec3[0])+','+str(vec3[1])+','+str(vec3[2])+'>>'
vecCrossProc=mel.eval('ReturnCrosProductList('+vecStr1+','+vecStr2+');')
#get crossProduct Vec
vecCrossVecStr='<<'+str(vecCrossProc[0])+','+str(vecCrossProc[1])+','+str(vecCrossProc[2])+'>>'
#get dotProduct length
vecDotProc=mel.eval('ReturnDotProductList('+vecStr3+','+vecCrossVecStr+');')
if len(str(vecDotProc).split('e'))>1:
vecDotProc=0
if vecDotProc>0:
errorFaceList.append(face)
except:
print ('skip ' + face)
#print errorFaceList
mc.select(errorFaceList)
getRecessedFace()

2016年1月4日月曜日

centos7 rc.localからだと起動スクリプトがうごかない。。。

以前svnserveを導入した際、rc.localにsvnserveの起動スクリプトを記述して、
サーバーの起動時にsvnserveが自動的に立ち上がるように設定したのですが、
単にこれだけだと、自動起動してくれないことが分かりました。

実は、centos7から従来のrc.localにとる起動スクリプト管理ではなく、systemedにて
起動スクリプトの管理を行うようになったようです。

…てか、本にもそう書いてあった。全然読んでないじゃん。orz


起動スクリプトの管理方法は、他サイト様にていろいろ紹介されてありますが、
方法は2つ。
①rc.localを従来通り使うか
②systemedに乗り換えるか

です。

①に関しては、単にrc.localに実行権限を与えてあげるだけでOK。
実際やってみて、OKでした。

chmod u+x /etc/rc.d/rc.local

参考サイト:http://kantaro-cgi.com/blog/etc-server/cant_run_rclocal_centos7.html

②に関しては、
 ・専用シェルスクリプトを用意し、
 ・「/etc/systemd/systemの下に、拡張子が .serviceのテキストファイルを作る。」
   →参考サイト:tire.retire ガジェット好きおじさんの日記 より引用
 ・systemedに登録してあげる。

参考サイト:http://tire-retire.blogspot.jp/2014/12/centos7rclocal.html
参考サイト:http://motw.mods.jp/shellscript/tutorial.html

僕は①を試したのち、今後のことも考えて、systemedの対応を進めてみました。
シェルスクリプトは書いたことがありませんでしたが、初心者の自分にも難しくはなかったです。

ただ、現状まだうまく自動起動設定ができていない状態です。
systemedはサービスの起動順序をいろいろ指定できるのですが、依存関係にあるサービスが立ち上がる前にsvnserveの自動起動スクリプトが実行されているのではないか、と考えています。

今のところ、現状サーバー再起動時に再度立ち上げないといけないものは少ないので、
しばらく手動で対応しますが、頃合いをみて再挑戦したいところです。