QUILoaderで読み込んだUIに コンテキストメニューを割り当てる

Pyside..未だにたいしたことを知らなくて、掲題の件について調べてみた。

QUILoaderで読み込まない場合、QMainWindow.contextMenuEvent(self, event) というのがイベントハンドラになるのだけど、QUILoaderで読み込んだものだとこの関数がトリガーされない。

で、調べてみると、こんな設定が必要だった。

self.(QWidget名).setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.(QWidget名).customContextMenuRequested.connect(self.contextMenuEvent)

要は、イベントが発生してもスルーされていただけで、設定しろよ。という話でした..チャンチャン..

コンテキストメニューの記述に関しては、このサイトとかにさらっとサンプルが置いてあったので参考にしました。

 

ちなみに、MayaPython&Pysideでパネル作っている場合に、sibokenで親ウィンドウをゴニョゴニョしているとメニューの解放処理の途中で意図しない状態になるようで、一回コンテキストメニューを選択すると次の表示が処理できないという状態にハマリました。。
現状、回避方法判らないので、コンテキストメニューを出す奴は仕方なく StayOnTopの属性設定を使ってます。orz

【その後】
2回目のメニュー表示が出来ない問題は、自分自身のダイアログを生成する際に、オーナー指定としてMayaのウィンドウを渡してなかったのが原因でした。。
uiファイルは widgetベースで作成して、自分自身はQDialogを継承して、uiloadで得たWidgetを自分の子としてLayout下に置けばOKでした。。。

『python pyside 親ウィンドウ』でググると簡潔に説明しているページがあったので、そっちも見てみると良いかもです。

コンパウンドとマルチ

“Nesting” compound Maya attributes

自身は値を持たない代わりに、1つ又は複数のアトリビュートを子に持つ特殊なアトリビュートのことをコンパウンドと呼んでいる。
上記のコマンド列は、ダイナミックアトリビュートによるコンパウンド作成例。

※この例を見る限り、値を持つアトリビュートもそれ自体が別のアトリビュートを子に持つ構成は作成できる。
※ただ、値を持つアトリビュートのタイプは’compound’にはならない。

※↑ 例えば “double3” のこと。これはMaya内部の専用定義として存在するもので、自分で新しく定義できるタイプのものではない。ユーザー定義するには’compound’を使う。

上記のコマンド列は、addAttrsコマンド解説にあるコンパウンド作成例。

上記のコマンド列は、rampノードのcolorEntryListアトリビュートの情報を照会したもの。
アトリビュートのタイプは’compaund’で、2つの子要素『position, color』を持つことが分かる。

また、’ramp.colorEntryList’については同時にmulti要素も持っているので、
ramp1.colorEntryList[~]のように配列指定で複数のコンパウンドの情報を管理している。

コンパウンドとマルチの情報は異なる扱いの要素だが、混同しやすいので注意が必要。

上記のように、”attributeQuery -at ~”で ‘compound’と帰ってくるものがコンパウンド。

上記のように、”attributeQuery -m ~”で 1(又はTrue)と帰ってくるものがマルチ要素。
マルチ要素のアトリビュートは、次のように書くことで作成できる。

「マルチ要素の中にマルチ要素」を作る場合も、コンパウンドで。

キャタピラ的な構造のサンプル

たまに要るかなーと思いつつもほったらかしていたので、作ってみた。

belt_drive_rig_test(Maya2014で作成)

カーブを引く (必要なら先に、車輪を配置)
rebuild Curveで 均一な CVに変換(カーブのパラメータは 0~1の範囲にする)
expressionにて、pointOnCurveを用いて 『パラメータ⇒ 座標』の変換
履帯1つ1つに座標設定。履帯の間隔はパラメータで調整
履帯同士は Aim Constraintで向きを設定(object upで 車軸方向を up vectorに設定)
パラメータについては locator1の座標を使って、必要に応じて移動量や回転量の計算をする
・0以下になると、符号が逆転して挙動が安定しないので、その場合は十分に大きな値を足してやる
・履帯はカーブに沿うので、パラメータは0~1の範囲で与えるように
またlocator1の座標をカーブを1周で0~1の範囲に変換して与える必要がある
カーブ1周の長さを求める必要があるが、実際は履帯の個数分の多角形の外周の長さになるので、少し短くなる点に注意
・車輪は1周の長さが『2π*r』。(r=半径)
移動距離を車輪の外周長で割ると、回転数が出るので、それに360を掛けて、車軸のrotateに設定。
サンプルでは、半径が大きい順に 1.0, 0.85, 0.7, 0.35なので、それを係数として更に与えている。

このままだとcvを動かすとカーブの長さが変わってしまうので、そこをなるべく変えないような仕掛けが欲しいところ。
でも、ちょっと弛みを上下させるくらいだったら、問題ないかなーと思っているけど、転輪のサスペンション駆動とかやった場合は、もうどうなるか不明..

また、1つ1つ手作業のセットアップは無駄が多いので、是非Pythonとかでズバッと設定を入れて欲しい。
Expressionもほぼ同じことの繰り返しなので、テキスト置換を駆使してサクッといきたい。

ふしょくふ

『不織布』と書くんですが、最近よく出回っているマスクの材料です。

最近まで “ふせんふ” かと思っていました。字にすると『不繊布』。
でも、一般的には『不織布』と書いて『ふしょくふ』と読むんだそうです。

結構消費されてるけどって話をしたので調べてみると、最近のマスクの原料は、いろいろあるんですね。
参考サイト

ハノイの塔

Windowsのコマンドラインにて『cscript hanoi.js』とか入れると、ハノイの塔の解が表示される。

スクリプト先頭の var num = 数値; の数値を変えるとより数の多い場合も処理する。
※表示的に『3,2,1』となっている時、右端の数が一番上に乗っているものです。

昔の人は頭良いなぁ..

参考サイト1
参考サイト2

Pythonスクリプトを実行ファイルに変換する

特に特殊でも何でもないけど、やったこと&やってみて分かった点のメモ。

・Pythonスクリプトは、py2exeで実行ファイル化できる。
・できるといっても、exe単体にはならなくて付随ファイルができるので、できたフォルダごと配布する必要がある。
・py2exeの方も、実行ファイルにスクリプトを食わせたら吐かれるのではなく、変換用スクリプトを書き、それをPythonスクリプトとして実行することで実行ファイルが生成される。

例えば、”hello.py”として 単に “Hello, Python.” と表示するスクリプトを実行ファイルにする場合..

まず以下の2つのスクリプトファイルを同じフォルダに作成する。(文字コードは UTF-8 を使用)


【hello.py】
# -*- coding: utf-8 -*-
print “Hello, Python.”


【setup.py】
# -*- coding: utf-8 -*-
from distutils.core import setup
import py2exe

setup(console=[‘hello.py’])


“setup.py” を実行すると、同じフォルダ上に build, distと名前の付いた2つのフォルダができる。

dist内には、”hello.exe” という名前の実行ファイルができている。
これが生成された実行ファイル。
コマンドラインでカレントディレクトリを、”dist” に設定しておき “hello” と打ち込めば “python hello.py” と同じ結果が得られる。

Windows OS での CPython 環境利用について

基本的に Python.org からWindows用インストーラをダウンロードし、指示通りインストール&設定を行えば動きます。

自分の場合は、会社ですでに環境を構築するツールがある上で、そこから外れた環境を別途用意して動作をさせたい場合などの環境構築したいなーってところで、全然Pythonに必要なことが判ってないので、まだ Pythonの入ってない Windowsにインストールしてみたりしながら調べてみた。

CPythonのインストーラは、コマンドプロンプトで動かすためのモジュールをHDD上に展開しつつ、レジストリ(HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.6)にいろいろ登録をする。インストーラを実行しただけだと、単にHDDにフォルダ作成して、必要ファイルがコピーされただけの状態にしか見えないけど。
コマンドプロンプトを起動しても、特に追加の環境設定など見当たらないし、Windowsの環境変数の設定にも、特に変更は見当たらなかった。

コマンドラインから使う時は、path やら PYTHONPATH への設定は、自分好みで設定すればOKということっぽい。また設定を終えないと、実行ファイルにパスが通っていないので、スクリプトは実行されない。
GUI上からのスクリプト実行についてはレジストリ登録済なので、スクリプト実行される。

下のようなスクリプトをメモ帳で書いて、test.py とかの名称で保存。保存したファイルをエクスプローラからダブルクリックしてみれば分かる。

import time
print ‘hoge fuga.’
time.sleep(5)

docs.python.jpの解説を見ると、ありがちの解説が書かれていた。
Pythonの環境設定についての説明

実行ファイル(python.exe)へは、環境変数:Path にてパスを通す。
モジュール類(ライブラリ)へは、環境変数:PYTHONPATH にてパスを通す。

ということで。

【追補】

それなりに詳しくないとなんのこっちゃって感じの話だが、 モジュールの検索 を見ると、こんな記述がある。

・追加で “アプリケーションのパス” を HKEY_CURRENT_USERHKEY_LOCAL_MACHINE の中の \SOFTWARE\Python\PythonCore\version\PythonPath のサブキーとして登録することができます。サブキーはデフォルト値としてセミコロンで区切られたパス文字列を持つことができ、書くパスが sys.path に追加されます。 (既存のインストーラーは全て HKLM しか利用しないので、 HKCU は通常空です)

“HKEY_CURRENT_USER” か “HKEY_LOCAL_MACHINE” というのは、レジストリエディタの大項目です。要は、レジストリにパス登録することで、WindowsのGUI上からPythonのスクリプトとかの呼び出し設定ができまっせーってことです。

最初の方に書いたように、コマンドプロンプト上で Pythonスクリプトを動かすには、まず Pythonにパスを通す必要があり、GUI上で動かす場合は基本なくてもOK。
このへんは、なんか片手落ちな感じが。
そもそも、レジストリ登録は普通の人は見ないし、仮に見たところで登録が膨大なので、最初から登録場所を知っていないと必要な情報はそうそう見付けられないだろう。

モジュールの追加などを行った場合には、GUI/コマンドプロンプトに関わらずスクリプトから呼び出せるようにする為に、環境変数・レジストリ双方の設定が必要..

ってことになるので、その必要がある場合は要注意。

【追補.2】

その後、ふと「そもそもインストーラなしでPython環境は成立するのか?」とか思い Python26フォルダを丸ごとコピー。
元の Python2.6をコントロールパネル>プログラムと機能 からアンインストールして、コピーしたフォルダを元の名前に戻してみたところ、コマンドプロンプトでpath設定しただけでは python26.dllにパスが通ってないというエラーが出て動かないことを確認。

Python26フォルダ階層化には同名のファイルが見当たらないので、いくつかのファイルが直接Systemのフォルダにインストールされているのかもしれない。

で、実際に調べてみると、Windowsの方はこんな情報が。
Windowsが使用するDLL検索パス(@MSDN)
またPython2.7環境で調べてみると、Python27.dllはC:\Windows\System32フォルダに入っていた。

PythonスクリプトをEXE化するツール(py2exe)を使った場合、実行ファイル生成されたフォルダにpython27.dllが一緒に入っているのを考えると、コマンドラインから実行する場合にはPython.exeと同じフォルダにdllを入れておいた方がわかりやすそうな気がする..

何故、SystemフォルダにDLLだけ入れてあるのかは謎。
また、他に関連するDLLがないのかどうかについても不明だが、必要なDLLがないよってエラーが出る場合には、Python.exeのフォルダにかき集めてやればOKだと思われる。

abxRenderLayer

CreativeCrash にも登録されている、RenderLayer保存&復元ツール。

使ってみたところ、確かにコネクションが砕けたRenderLayer設定もある程度復元してくれる模様。

レイヤー設定の保存も出来るが、出力するのはあくまでもObjectやShadingGroupの関連が主な情報。
RenderLayerで上書きしているShaderノード本体の方は出力しないので、レイヤーに関連する情報が全て保証されると思っていると痛い目に会いそう..

しかし、かなり頑張って作ってあるので、RenderLayerが壊れて困っている人には救世主になる..かも?
中身はMELで記述されているので、不満がある人は abxRenderLayerをベースに自分で手を加えてみるのもいいかもしれない。

’14/04/27現在。
v1.5が$20で、販売されています。

砕けたデータに復活の呪文を唱えたいだけなら、こういうコマンドもあるのですね。

レンダレイヤ 調査

Maya起動直後の状態。

defaultRenderLayer_justAfterBoot

レイヤーを作成。
ChannelEditor下の Renderタブにて。

renderLayer_UI_sample

レイヤーを追加すると、ノード構成はこんな感じ。
defaultRenderLayerには基本すべてのオブジェクトが属する。その他のLayerに対してのみ追加削除が行われ、その際にコネクションが作成される。
defaultRenderLayer_AddLocator1ToLayer1

Layer2を作成。
よく判らなくなってきたので、要所の接続を調べてみた。
※renderLayerManager->, ->defaultRenderingList1, ->locator1
defaultRenderLayer_addLayer2

renderLayerの並びを変えてみたが、コネクションは変化なし。
細かく調べると、Layerのアトリビュート(.do)の値が変化していた。defaultRenderLayer_changeLayerOrder

renderLayer_displayorder


masterLayer は、内部的には defaultRenderLayer という名称のノード。
renderLayerManager は、レンダレイヤ全体の管理ノード。renderLayer_simpleNodeConnection_sample

Layer1 にpSphere1を追加すると、こんな構成になる。
Layer1 → pSphere1 というコネクションが見える。
(メンバとしての、コネクションが作られている。
これは defaultRenderLayerの場合には存在せず、全てが属している扱い。)

renderLayer_simpleNodeConnection_sample2

さらに、pSphere1に phong1シェーダーを追加。
今度は pSphereShape1 → layer1 の入力が見える。

renderLayer_simpleNodeConnection_sample3

また、layer1 → phong1SG への入力が見える。

renderLayer_simpleNodeConnection_sample3b

lightlink の場合は、以下のような具合に。

renderLayer_default_lightLinkConnection_sample renderLayer_lightLinkConnection_sample

break lightlink を使ってライトの影響下からオブジェクトを外したら、
以下のようなコネクションが生成される。
(影響を受けない、ということを示す接続ができるパターンも存在する。ということで。)

renderLayer_lightLinkConnection_sample2

color アトリビュートを override した場合は、以下のような感じ。
phong1 → layer1, defaultRenderLayer にそれぞれ入力されているのが見える。
( phong1.color からの接続ができている。)renderLayer_simpleNodeConnection_sample4

renderLayer_simpleNodeConnection_sample4b

 

コネクションのことしか見ていないが、実際はアトリビュートの状態も見てsetAttr文を生成しないといけない..

プロジェクト設定 – 表示形式:タイムコードベース時の fps値取得 など

以下、覚え書き。

// AfterEffects CS5 で確認
// 表示形式: タイムコードベース時の fps値取得
{
var fps = 0;
switch(app.project.timecodeBaseType){
case TimecodeBaseType.FPS100:  fps = 100; break;
case TimecodeBaseType.FPS24:  fps = 24; break;
case TimecodeBaseType.FPS25:  fps = 25; break;
case TimecodeBaseType.FPS30:  fps = 30; break;
case TimecodeBaseType.FPS48:  fps = 48; break;
case TimecodeBaseType.FPS50:  fps = 50; break;
case TimecodeBaseType.FPS60:  fps = 60; break;
}
alert( fps );
}

//フィート+フレーム
{
var mm = 0;
switch(app.project.timecodeFilmType){
case TimecodeFilmType.MM16:  mm = 16; break;
case TimecodeFilmType.MM35:  mm = 35; break;
}
alert( mm );
}

//表示形式: タイムコードベース/フレーム/フィート+フレーム
{
var typename = “”;
switch(app.project.timecodeDisplayType){
case TimecodeDisplayType.FEET_AND_FRAMES:  typename = “Feet+Frames”; break;
case TimecodeDisplayType.FRAMES:  typename = “Frames”; break;
case TimecodeDisplayType.TIMECODE:  typename = “Timecode”; break;
}
alert( typename );
}

//開始フレーム番号
alert( app.project.displayStartFrame );

その後

CS6から”app.project.timecodeBaseType”とかなくなってた…今更そんな事知るとは…orz