modo Script Python 頂点法線と頂点カラーの変換

# python
import lx
cmap = []
nmap = []
uvmap = []
for x in lx.eval("query layerservice vmaps ?"):
	vmapName = lx.eval("query layerservice vmap.name ? {0:}".format(x))
	vmapType = lx.eval("query layerservice vmap.type ? {0:}".format(x))
	if vmapType=="rgba":
		cmap.append(vmapName)
	if vmapType=="normal":
		nmap.append(vmapName)
	if vmapType=="texture":
		uvmap.append(vmapName)
if nmap:
	if cmap:
		lx.eval("select.vertexMap {0:} rgba replace".format(cmap[0]))
		lx.eval("!!vertMap.delete rgba")
	lx.eval("vertMap.new Color rgba true {0.0 0.0 0.0} 1.0")
	lx.command("vertMap.math",dest="RGBA[4]:Color",map0="NORM[3]:{0:}".format(nmap[0]),scale0=0.25,offset0=1,mode0="direct",index0=0,map1="NORM[3]:{0:}".format(nmap[0]),scale1=0.25,offset1=1,mode1="direct",index1=0)
	lx.eval("select.vertexMap Color rgba replace")
	if uvmap:
		lx.eval("select.vertexMap {0:} txuv replace".format(uvmap[0]))
# python
import lx
cmap = []
nmap = []
uvmap = []
for x in lx.eval("query layerservice vmaps ?"):
	vmapName = lx.eval("query layerservice vmap.name ? {0:}".format(x))
	vmapType = lx.eval("query layerservice vmap.type ? {0:}".format(x))
	if vmapType=="rgba":
		cmap.append(vmapName)
	if vmapType=="normal":
		nmap.append(vmapName)
	if vmapType=="texture":
		uvmap.append(vmapName)
if cmap:
	if nmap:
		lx.eval("select.vertexMap {0:} norm replace".format(nmap[0]))
		lx.eval("!!vertMap.delete norm")
	lx.eval("vertMap.new Normal norm true {0.0 0.0 0.0} 1.0")
	lx.command("vertMap.math",dest="NORM[3]:Other",map0="RGBA[4]:{0:}".format(cmap[0]),scale0=1,offset0=-0.5,mode0="direct",index0=0,map1="RGBA[4]:{0:}".format(cmap[0]),scale1=1,offset1=-0.5,mode1="direct",index1=0)
	lx.eval("select.vertexMap {0:} rgba replace".format(cmap[0]))
	if uvmap:
		lx.eval("select.vertexMap {0:} txuv replace".format(uvmap[0]))

あまり需要はないかと思いますが、頂点法線マップと頂点カラーマップの変換です。
上の方が頂点法線を頂点カラーに変換するもので、下のものがその逆です。
 

modoの法線マップはマニュアルにもあったかと思いますが、あくまでも補助的なもので、細かく調整するものではない。
という発想で作られているそうです。
確かに大した編集はできない。
しかし、それをカラーマップにすることで、だいぶ編集が可能になります。もちろんオブジェクト法線ですが。

 

それにしてもmodoのスクリプト、作りにくい、、
オブジェクト指向になれると、手続き型のものがまどろっこしく感じてしまう。
しかし、チューリングの時からコンピュータの基礎中の基礎は手続き型なのだし、汎用性の高いプログラムとなると、
確実にそういった部分が必要なのだろうと思う。
でも、evalで文字列としてコマンドを渡りたりlx.command()のような形でカッコつきでコマンドを入力しなければならないのはいかがなものだろうか。
カッコが多すぎて見難い。

modo Script Python パースビューのワイヤーフレームオーバーレイ切り替え

# python
import lx

wlist = ["colored","uniform","none"]
lx.eval("select.viewport fromMouse:1")

if lx.eval("viewport.type ?")=="3Dmodel":
	cwcolor = lx.eval("viewport.3dView wireframe:?")
	nwcolor = wlist[wlist.index(cwcolor)-1]
	lx.eval("viewport.3dView wireframe:{0:}".format(nwcolor))

modoのスクリプトです。
今までどこかで拾ってきたのか知りませんが、パールで書かれたワイヤーフレームオーバーレイの切り替えスクリプトを使っておりました。
取り立てて問題はないのですが、「なし」、「同一」、「色付き」を順番に切り替える必要が出てきました。
で、Pythonで作ってみました。

 

実行するごとに順に切り替わります。
しかし、Mayaのスクリプト開発になれると、modoのスクリプト開発はちょっと大変だ。
エラーメッセージが明確ではない。
きちんとできているはずなのにおかしいなぁ、としばらく格闘しておりました。
原因ははじめに設定したリスト内でのスペルミスです。
エラーでは、index()メソッドにはリストは入らないよ。というようなことが出てきいました。
リストは入れていないのになぁ、としばらく途方に暮れてしまいました。
Mayaであれば、そんな文字列は入らないよ、とその文字列も表示してくれます。
Mayaにおんぶにだっこです。

 

しかし、頂点マップのスムーズ機能のバグは直らないのだろうか。
パーセントを設定しても効いてくれない。スキニングのノーマライズが効かなくなる。
頂点カラーはスムーズ後、カラーを設定しようとすると、正しく設定できない。
地味に不便だ。
スムーズ後に値を設定する場合は、そのマップをコピーして、新たなマップで設定し直すと回避できる。
というバグ回避の技が身についてしまった。
出来れば頂点カラーを画像として出力できるきちんとした方法もあるとありがたい。
実はウェイトマップの出力で裏技的にできることもあるが、それなりの頻度でmodoが落ちる。

Maya Script Pymel 選択範囲の記憶 その2 ScriptJob

恥ずかしながら、またバグがありました。
大したデバッグをしておりませんでした。すみません。
気がついたきっかけは、似たようなスクリプトの構造でカラーテクスチャとノーマルテクスチャを入れ替えるスクリプトを使った時でした。
スクリプトを使用し、再び同じシーンを開いてスクリプトを実行すると、エラーが帰って来ました。
場合によってはMayaが落ちました。
どうもエラーメッセージを見てみると、そんなオブジェクト存在しないよ。というようなことが書いてありました。
同じシーンから取ってきたのだから、同じじゃないの?と思っていたのですが、違うようです。
で、解決方法としては、シーンを開くたびにメモリを初期化すれば良いじゃないか。
ということで、scriptJobを使いました。以前ウェイトエディタを作った時にも使ったのですが、
あれは、UIにペアレントされていたので、UIを消せば消えるので気軽に使えました。
しかし、今回の場合UIがないので、そうも行きません。
なので、またuserSetup.pyだのみです。

import pymel.core as pm

class MemSel(object):
	vsel = []
	esel = []
	fsel = []
	uvsel = []

mem = MemSel()

def mem_clear():
	mem.vsel = []
	mem.esel = []
	mem.fsel = []
	mem.uvsel = []

def mem_clear_sjob():
	sjob = pm.scriptJob(e=["SceneOpened","mem_clear()"])
mem_clear_sjob()

def selection(mode):
	sel = pm.selected() if pm.selected()!=[] else pm.ls(hl=1)
	if sel:
		if mode == "object":
			pm.selectMode(o=1)
		else:
			pm.selectMode(co=1)
		if type(sel[0]) == pm.nodetypes.Mesh:
			name = sel[0]
		elif type(sel[0]) == pm.nodetypes.Transform:
			name = sel[0].getShape()
		else:
			name = sel[0]._node
		if type(sel[0]) == pm.MeshVertex:
			if mem.vsel != sel:
				mem.vsel = sel
		if type(sel[0]) == pm.MeshEdge:
			if mem.esel != sel:
				mem.esel = sel
		if type(sel[0]) == pm.MeshFace:
			if mem.fsel != sel:
				mem.fsel = sel
		if type(sel[0]) == pm.MeshUV:
			if mem.uvsel != sel:
				mem.uvsel = sel
				pm.select(cl=1)
		if mode == "vertex":
			pm.selectType(smp=1,sme=0,smf=0,smu=0,pv=1,pe=0,pf=0,puv=0)
			if mem.vsel and mem.vsel[0].split(".")[0] == name :
				pm.select(mem.vsel)
			else:
				pm.select(cl=1)
		if mode == "edge":
			pm.selectType(smp=0,sme=1,smf=0,smu=0,pv=0,pe=1,pf=0,puv=0)
			if mem.esel and mem.esel[0].split(".")[0] == name :
				pm.select(mem.esel)
			else:
				pm.select(cl=1)
		if mode == "face":
			pm.selectType(smp=0,sme=0,smf=1,smu=0,pv=0,pe=0,pf=1,puv=0)
			if mem.fsel and mem.fsel[0].split(".")[0] == name :
				pm.select(mem.fsel)
			else:
				pm.select(cl=1)
		if mode == "uv":
			pm.selectType(pv=0,pe=0,pf=0,puv=1,smp=0,sme=0,smf=0,smu=1)
			if mem.uvsel and mem.uvsel[0].split(".")[0] == name :
				pm.select(mem.uvsel)
			else:
				pm.select(cl=1)

C:\Users\(ユーザー名)\Documents\maya\2013-x64※バージョン名\ja_JP\prefs\scripts\userSetup.py
に記述することで使えます。
うーん、賢くない。一層のこと関数にアトリビュートを持たせてやったほうが良いのだろうか?
まぁ、使えるからいいや。

 

因みに、scriptJobですが、

import pymel.core as pm
for x in pm.scriptJob(lj=1):
	print x.split("\n")[0]

このようにすると、すでに発行されているscriptJobを確認することができます。
デフォルトで100個近くあるのですね。ちょっとびっくりです。
だったらひとつくらい、良いかな。そんな軽い気持ちになれます。

Maya Script Pymel 選択範囲の記憶

import pymel.core as pm

class MemSel(object):
	sceneName = ""
	vsel = []
	esel = []
	fsel = []
	uvsel = []

mem = MemSel()

def selection(mode):
	sname = pm.Env().sceneName()
	if mem.sceneName != sname:
		mem.sceneName = sname
		mem.vsel = []
		mem.esel = []
		mem.fsel = []
		mem.uvsel = []
	sel = pm.selected() if pm.selected()!=[] else pm.ls(hl=1)
	if sel:
		if mode == "object":
			pm.selectMode(o=1)
		else:
			pm.selectMode(co=1)
		if type(sel[0]) == pm.nodetypes.Mesh:
			name = sel[0]
		elif type(sel[0]) == pm.nodetypes.Transform:
			name = sel[0].getShape()
		else:
			name = sel[0]._node
		if type(sel[0]) == pm.MeshVertex:
			if mem.vsel != sel:
				mem.vsel = sel
		if type(sel[0]) == pm.MeshEdge:
			if mem.esel != sel:
				mem.esel = sel
		if type(sel[0]) == pm.MeshFace:
			if mem.fsel != sel:
				mem.fsel = sel
		if type(sel[0]) == pm.MeshUV:
			if mem.uvsel != sel:
				mem.uvsel = sel
				pm.select(cl=1)
		if mode == "vertex":
			pm.selectType(smp=1,sme=0,smf=0,smu=0,pv=1,pe=0,pf=0,puv=0)
			if mem.vsel and mem.vsel[0].split(".")[0] == name :
				pm.select(mem.vsel)
			else:
				pm.select(cl=1)
		if mode == "edge":
			pm.selectType(smp=0,sme=1,smf=0,smu=0,pv=0,pe=1,pf=0,puv=0)
			if mem.esel and mem.esel[0].split(".")[0] == name :
				pm.select(mem.esel)
			else:
				pm.select(cl=1)
		if mode == "face":
			pm.selectType(smp=0,sme=0,smf=1,smu=0,pv=0,pe=0,pf=1,puv=0)
			if mem.fsel and mem.fsel[0].split(".")[0] == name :
				pm.select(mem.fsel)
			else:
				pm.select(cl=1)
		if mode == "uv":
			pm.selectType(pv=0,pe=0,pf=0,puv=1,smp=0,sme=0,smf=0,smu=1)
			if mem.uvsel and mem.uvsel[0].split(".")[0] == name :
				pm.select(mem.uvsel)
			else:
				pm.select(cl=1)

相変わらず稚拙なコードです。
でもなんとかできました。
ただ、自分が使うもの限定なので、ポリゴンメッシュのみに対応しております。
XSIと違い、それぞれのオブジェクトの選択範囲を記憶するのではなく、頂点、エッジ、フェース、UV
をそれぞれ一つだけ記憶できます。
オブジェクトごとにインスタンスを作れば複数オブジェクトにも対応できるのだとは思います。
そこまで求めておりません。
このスクリプトを作っていて、モデリングはmodoで済ませるから、使わないよな。でも作ってみたいなぁ。
という中途半端な気持ちで作っていたので、コードも中途半端です。

 

クラスをただの箱としてしか使っていない。
最初は中で色々やるようにしていたのですが、スーパークラスが必要になりそうなので、
まだクラスの知識もおぼつかないし、そこまで求めていないし。とこんな形になりました。

 

しかし、地味に便利です。これくらいで十分だ。
userSetup.pyに書き込んでおくとホットキーで使えます。
使い方は、

selection("vertex")

で頂点選択

selection("edge")

でエッジ選択

selection("face")

でフェース選択

selection("uv")

でUV選択

selection("object")

でオブジェクト選択です。
因みに自分の場合は、オブジェクト選択に、

pm.runtime.SelectTool()

と、2行目を追加し、オブジェクト選択モードに変更すると同時にセレクトツールに移行させております。
ツールドロップのような役割を果たします。
これも選択範囲が記憶されているので、使い勝手は十分だと思います。
そして、割り当てるキーはmodoと同じ、それぞれ「1」、「2」、「3」、uvが「Ctrl」+「1」です。
で、オブジェクト選択は「q」です。おぉ、modoのように使いやすい。と感激します。

 

そして、クラスを箱として使い、メモリに格納したい情報を置いておける。という利点をいいことに、
ノーマルマップが貼られているマテリアルのカラーとノーマルを入れ替えるものなども作ってみました。
しかし、職場では問題なく動作するのに自宅では動かない。
どうやらPymelでマテリアルを取得するだけでエラーが帰ってきます。
2012と2013の違いなのでしょうか?他の環境を知らないので分からない。
やはりこういう時にAPIの知識が必要なんだろうなぁ、と感じてしまいます。
API勉強すればC++への移行も少しはしやすいんだろうなぁ。
まぁ、気が向いたらやります。

Maya Script Pymel イメージの読み込み

うーん、オブジェクティブ、難しいなぁ、、
使うのは簡単だが、自分で作るとなると難しい、まだ理解が足りない。
先日記事を書いていて、選択範囲を記憶しておくことは、クラスを使えば案外簡単にできそうだ、
と、やってはいるのですが、中々うまく行かない。自分の不理解が原因だ。

 

それはそうと、タイトル通りに、イメージの読み込みについて書きます。
Mayaではウィンドウズ上からハイパーシェードにドラッグアンドドロップでイメージを追加できます。
その時実行されるmelの関数が、「importImageFile()」です。
引数を見ると、イメージのパス、その他ブーリアンのフラグがあるようです。
で、それで画像を読み込むと画像のノード名が、「画像のファイル名」+「_1」といった感じになります。
以前は面倒だったので、スクリプトの途中で、この関数を使って画像を読み込み、名前を変更する。
という手段をとっておりました。
改めて、関数の中を覗いてやっている処理を大雑把に見てみました。
で、結局

import pymel.core as pm
imagepath = r"C:\Users\a\Pictures\test.tga"
fileNode = pm.shadingNode("file",at=1)
fileNode.ftn.set(imagepath)
fileNode.rename(imagepath.rsplit("/",1)[1].split(".")[0])

と、なりました。
大雑把に見ただけなので、色々と見落としている部分があるかと思いますが、
一応使えているので、よしとします。
で、以前画像のリロードについて書いたかと思いますが、それをpymelでやると、

import pymel.core as pm
[y.ftn.set(y.ftn.get()) for y in pm.ls(typ="file",type="mentalrayTexture")]

となるようです。
またもや見やすい上にわかりやすい。
もっと理解を深めたい。

Maya Script Pymel コンポーネント選択でトランスフォームノードを取得

なんだか意味の分からないタイトルです。
コンポーネント選択時(頂点選択、エッジ選択、フェース選択)、にスクリプトからトランスフォームノードを捕まえられるのか。という話です。
なぜ、それが必要になったか。はっきり言って勘違いでした。
あえて恥を晒す必要もないのですが、メモ帳代わりに書いておきます。

 

そもそもやろうとしていることが、法線方向の表示をコンポーネント選択の時でもオン、オフが切り替えられるといいのになぁ。
ということがきっかけです。
modoはレイヤーを変えない限りは選択範囲を覚えているし、新たに選択するとしても選択自体が簡単なので、問題ない。
Mayaではそのどちらにも問題があるので、いちいちオブジェクト選択に戻して、選択し直すのが面倒くさい。
そんな横着な発想から始まりました。そもそもスクリプトを作るのは横着な発想からであることが大半だ。

 

それはさておき、
Mayaの構造を相変わらず詳しく知りません。
なので、法線表示のアトリビュートはトランスフォームノードにあるのだとばかり思っておりました。ただの思いこみです。
なので、トランスフォームノードを取得する必要があるのだろう。と、探していると、望みの物を見つけました。
ただ、相変わらず、そのままだと若干不都合がある。なので、改造しました。

import pymel.core as pm
pm.selected()[0]._node.getParent()

コンポーネント選択で、何かを選択し、上記のスクリプトを実行するとトランスフォームノードを取得できます。
Mayaの構造知りませんが、シェイプノードの親は確実にそれのトランスフォームノードなのでしょうか?
確実にトランスフォームを取得する、という点では、

import pymel.core as pm
pm.selected()[0]._node.listRelatives(ap=1,type="transform")

こうなるのでしょうか?そこまでする必要もない。長ったらしい記述を見ていると自分でもそう思います。
で、そんな誤解と不理解からこんなスクリプトを作ってしまいました。

import pymel.core as pm
for x in pm.selected(o=1):
	if type(x) != pm.nodetypes.Transform:
		pm.setAttr(pm.PyNode(x).getParent()+".displayNormal", not pm.getAttr(pm.PyNode(x).getParent()+".displayNormal"))
		pm.setAttr(pm.PyNode(x).getParent()+".normalType",2)
	else:
		pm.setAttr(x+".displayNormal", not pm.getAttr(x+".displayNormal"))
		pm.setAttr(x+".normalType",2)

うーん、馬鹿丸出しです。
まぁ、動作はするし、別に問題があるわけではないのですが、せっかくのオブジェクト指向が無駄になっている。
その後色々と調べたり、実験したりしているうちにようやく法線方向の表示はシェイプノードにあることに気が付きました。
それはそうだ。と当然のように納得し、早速作り直しました。

import pymel.core as pm
for x in pm.selected(o=1):
	x.displayNormal.set(not x.displayNormal.get())
	x.normalType.set(2)

おお、わかりやすく読みやすい。と感動してしまいました。
コマンドとして入力しなくても、すでにオブジェクト自体にそのアトリビュートを持っております。
少しずつ、Mayaの構造とオブジェクト指向を学んでおります。

Maya Script mel whatIs

melには「whatIs」というコマンドがあります。
コマンドがどういったものであるのか、実行したmelの関数がどこにあるのか、ということが調べたい時に使います。
スクリプトエディタを起動しながら、GUIでコマンドを実行し、表示されるコマンドを確認します。
そのコマンドをコピーしておき、スクリプトエディタに、

whatIs("performPolyMergeUV")

と、melタブで入力すると、

// 結果: Script found in: C:/Program Files/Autodesk/Maya2013/scripts/others/performPolyMergeUV.mel // 

といった感じに実行した関数が記述されているファイルを特定することができます。
因みに上記の物は、UVエディタにある、「選択したエッジまたはUVの縫合」です。
で、それをPythonの方からできないものか、と検索してみると、次のような記述を見つけました。

import pymel.tools.mel2py as mel2py
mel2py.melInfo('attributeExists')

戻り値を見ると、意図しているものとはちょっと違うように思いますが、とにかく実行してみました。
エラーが帰ってきます。
英語が不慣れなため、詳細はわかりませんが、どうやら同じようなことが海外でもチラホラと話題になっているようでした。
マニュアルを見ると、mel2pyのモジュールについて、他にも書かれていたので、見てみました。

import pymel.tools.mel2py as mel2py
mel2py.fileOnMelPath("performPolyMergeUV")

このようにすると、melでwhatIsを実行した時と同じ表示がなされます。
しかしやはりモジュールの読み込みでワーニングが出ます。
だったら、

import pymel.core as pm
pm.mel.whatIs("performPolyMergeUV")

これで良いじゃないか。
pymelをインポートすると、maya.melをインポートしなくても上記のやり方でmaya.melを使うことができます。

 

色々調べた挙句に結局それかよ。と自分で突っ込みたくなる出来事でした。

Maya Script Pymel 選択タイプを取得

Pymelをせっかく使っているので、選択されたものが何であるのかを見て、
それによって、分岐させたい。そんなことを考えて色々と試しておりました。

 

今までどおりのPythonであれば、最悪、

import maya.cmds as cmds
cmds.ls(sl=1)[0].split(".")[1].find("vtx")

などと、文字列に変換して調べる。という方法もありました。
しかし、せっかくオブジェクト指向なので、それを活用した方法はないものか、
検索をしてみると、どうやら同じようなことを考えている人たちはいるようで、
いくつかのものを発見することができました。
しかし、どれもうまく行かない、、
それらを参考にして作ってみました。

import pymel.core as pm
for x in pm.selected(fl=1):
	if type(x) == pm.MeshFace:
		print "MeshFace"
	if type(x) == pm.MeshVertex:
		print "MeshVertex"
	if type(x) == pm.MeshEdge:
		print "MeshEdge"
	if type(x) == pm.MeshUV:
		print "MeshUV"
	if type(x) == pm.MeshVertexFace:
		print "MeshVertexFace"
	if type(x) == pm.nodetypes.Transform:
		print "Transform"
	if type(x) == pm.nodetypes.Mesh:
		print "Shape"
	print x

このコードでは、頂点、エッジ、フェース、UV、頂点フェース、トランスフォーム、シェイプを判断できます。
これが最良の方法かどうかは知りませんが、とりあえず判別できます。
で、それで何か作ってみよう、と、こんなものを作りました。

import pymel.core as pm
edges = pm.ls([pm.polyListComponentConversion(x,te=1) for x in pm.selected(fl=1)if type(x)==pm.MeshFace],fl=1)
edgesSet = set(edges)
[edgesSet.remove(x) for x in list(edgesSet)if edges.count(x)>1]
if edgesSet!=set():
	pm.select(edgesSet)

選択されたものがフェースであるかを判別し、実行するようにしております。
フェース選択の境界にあるエッジを選択するものです。
作り終えて、動作を見た時に、見たことのある動作だ、ということに気が付きました。
よくよく考えてみると、以前作ったものを記事として書いている。
すっかり忘れておりました、、ただのバカです。
まぁ、こんな書き方もあるよ。と、自分に言い聞かせて納得するよりほかありません。

 

しかし、過去の記事、ところどころコードの文字が化けていますね、、使いものにならない。
メモ代わりに使っているので、元もない。仕方がない。

Maya Script Pymel ハードエッジの選択

以前Pythonでハードエッジの選択をするものを公開しました。
Pymelだとエッジのメソッドにハードエッジの検出をする機能があったので、試しに作ってみました。

import pymel.core as pm
pm.select([x for x in pm.ls(pm.selected()[0].node().e,fl=1) if x.isSmooth()==False],r=1)

ただし単一オブジェクトのみです。

 

そしてこちらが複数オブジェクト対応です。

import pymel.core as pm
pm.select([z for z in pm.ls([pm.ls(y.e,fl=1) for y in set(x.node() for x in pm.selected())])if z.isSmooth()==False],r=1)

相変わらず、ここまでしてリスト内包表現に拘る必要はないだろう。
と、思っているのですが、何となくできないと悔しいので、やってしまいます。

 

それはともかく、Pymelだと簡単に書くことができます。
しかし、cmdsと比べて一つ一つの頂点を検索してゆくのは遅いような気がします。
やり方が悪いのでしょうか?

Maya Script Python 可変長のリストを文字列フォーマットで出力

タイトルにMayaと書きながら、Mayaは関係ないです。
Pythonのカテゴリーも作ったほうが良いのか、迷うところですが、そのうち溜まったら作ります。

 

しかも内容がくだらないのですが、どうしても可変長のリストを整形した形で出力したく、
色々と方法を考えておりました。
因みに最初に試みた方法です。

list = ["abcdef","ABCDEF","123456","bcdefg","BCDEFG"]
print "{0:<25}{1:<25}{2:<25}".format(*list)

format関数に「*」(アスタリスク)をつけてリストを入れてやると、リストを展開して関数に渡してくれます。
出力結果は、

abcdef                   ABCDEF                   123456                   

こんなかんじです。
確かに可変長のリストを展開してくれるのですが、指定した範囲を超えたものは削除されます。
当然といえば当然です。
そして、指定した長さに至らない場合は、エラーが帰ってきてしまいます。なので、ダメです。

 

どうにか綺麗で見やすい書き方はないものだろうか。
結局こうなりました。

list = ["abcdef","ABCDEF","123456","bcdefg","BCDEFG"]
pstring = []
for i,x in enumerate(list):
	pstring.append("{0:<2}".format(i+1)+":{0:<25}".format(x))
	if (i+1)%3==0:
		pstring.append("\n")
print "".join(pstring)

出力結果は、

1 :abcdef                   2 :ABCDEF                   3 :123456                   
4 :bcdefg                   5 :BCDEFG                   

こんなかんじです。
うーん、もっとスマートな書き方があるような気がしますが、思いつきませんでした。

 

そういえば、スクリプトを書いているときに、以前書いた記事を参考にしよう、と自分のページの記事を見ました。
どうやらいくつか見られない記事があるようです。
不精してパーマリンクを日本語のままにしたからでしょうか?良く分かりません。
そのうち気が向いたら直します。
なにせ、そこに書いてあるスクリプトが文字化けしていて、元のスクリプトがどこにあるのかわからない。
探すのが面倒なので、放置しておきます。

アニメーションが親切に解説されております

レンダリング、ライティングの基本が分かります

図版が見やすい美術解剖書です