3dsmax 2015 版本之后開(kāi)始支持python,使用MAXScript可以跳轉(zhuǎn)到python文件的執(zhí)行
python.ExecuteFile @"C:\Program Files\Autodesk\3ds Max 2015\scripts\Python\demoBentCylinder.py"
對(duì)于我這種E文不好、python不好、3dsmax也不好的“三不好青年”,來(lái)完成插件開(kāi)發(fā),那可真是廢了事情了。一直寫慣了靜態(tài)語(yǔ)言,并且有強(qiáng)大開(kāi)發(fā)環(huán)境支持,代碼提示+調(diào)試+重構(gòu),沒(méi)有這三個(gè)利器,簡(jiǎn)直寸步難行,為此,就來(lái)一一解決這些問(wèn)題,記錄了探索的過(guò)程。
查閱歷史
百度谷歌搜尋一遍,找一下python開(kāi)發(fā)3dsmax的信息,發(fā)現(xiàn)啥都沒(méi)有,僅有的一些就告訴你,如何通過(guò)ms來(lái)執(zhí)行python文件,以及官方的幫助文檔,官方文檔告訴你api,但是如何順暢地搭建開(kāi)發(fā)調(diào)試環(huán)境沒(méi)有任何說(shuō)明。
官方可用文檔2016:https://pan.baidu.com/s/1QAtOARo07zSzLqDnfPBeOg
提取碼:j6tj
材料
- 3dsmax 2016
- pycharm
創(chuàng)建項(xiàng)目
使用pycharm 創(chuàng)建純的python項(xiàng)目,==目錄不要帶有空格==, python環(huán)境使用3dsmax安裝目錄下自帶的python,{軟件安裝目錄}\autodesk\3ds Max 2016\python\python.exe

解決代碼引用和提示問(wèn)題
插件API都是從 MaxPlus 這個(gè)模塊入手的,我們自己寫的代碼就得 import MaxPlus,發(fā)現(xiàn)直接導(dǎo)入的時(shí)候,IDE提醒找不到對(duì)應(yīng)的模塊,也就沒(méi)有什么代碼提示了和查閱了,==所以第一步就是要找到MaxPlus的接口python文件==
在3dsmax安裝目錄下搜索 “maxplus”,發(fā)現(xiàn)有對(duì)應(yīng)可用的py文件

將MaxPlus.py文件拷貝到我們的項(xiàng)目文件下,這樣自己寫的代碼就可以直接導(dǎo)入MaxPlus,并且可以隨時(shí)查看源碼。

編寫代碼并且執(zhí)行
- 啟動(dòng)3dsmax的maxscript的執(zhí)行環(huán)境。
- 菜單->Scripting->MAXScript Listener
-
菜單->Scripting->MAXScript Editor
圖片.png
- 項(xiàng)目建立test.py, 添加如下示例代碼,代碼可以在幫助文檔中找到。
test.py
import sys
import MaxPlus
obj = MaxPlus.Factory.CreateGeomObject(MaxPlus.ClassIds.Cylinder)
obj.ParameterBlock.Radius.Value = 10.0
obj.ParameterBlock.Height.Value = 30.0
node = MaxPlus.Factory.CreateNode(obj)
mod = MaxPlus.Factory.CreateObjectModifier(MaxPlus.ClassIds.Bend)
mod.ParameterBlock.BendAngle.Value = 45.0
node.AddModifier(mod)
obj = MaxPlus.Factory.CreateGeomObject(MaxPlus.ClassIds.Sphere)
for p in obj.ParameterBlock.Parameters:
print p.Name, p.Value
- 項(xiàng)目中建立start.ms, 用來(lái)啟動(dòng)python, 其實(shí)也可以每次手動(dòng)輸入
start.ms
python.ExecuteFile @"E:/code/3dsmax/test.py"
其中test.py文件地址自己替換。
- 執(zhí)行
使用MAXScript Listener 菜單 file->run script 執(zhí)行項(xiàng)目目錄下的start.ms, 觀察結(jié)果,可以在3dsmax中添加一個(gè)圓柱體

解決調(diào)試問(wèn)題
不能調(diào)試的代碼,開(kāi)發(fā)效率至少也得下降一半,除非是大神級(jí)別,并且把單元測(cè)試給補(bǔ)全了,一般人就是依賴調(diào)試工具,才能迅速定位問(wèn)題點(diǎn)。
沒(méi)有調(diào)試的支持
編碼五分鐘,log一小時(shí), 加班一整夜。
反之
編碼一小時(shí),調(diào)試五分鐘, 收工。
當(dāng)我們使用pycharm進(jìn)行python調(diào)試的時(shí)候,發(fā)現(xiàn)console會(huì)打印
"D:\Program Files\autodesk\3ds Max 2016\python\python.exe" "D:\Program Files\JetBrains\PyCharm 2018.1\helpers\pydev\pydevd.py" --cmd-line --multiproc --qt-support=auto --client 127.0.0.1 --port 55220 --file E:/code/3dsmax/test.py
pydev debugger: process 5784 is connecting
Connected to pydev debugger (build 181.4203.547)
hello world
第一行是一個(gè)執(zhí)行命令, 第二行是debugger進(jìn)行socket連接,第三行是連接成功,第四行是py文件的執(zhí)行打印。
調(diào)試的過(guò)程可以推測(cè)為:
- 使用pydevd.py創(chuàng)建調(diào)試環(huán)境,執(zhí)行目標(biāo)文件,并且與當(dāng)前pycharm進(jìn)行socket連接
- 連接成功,傳輸斷點(diǎn)信息,以及執(zhí)行過(guò)程
既然是命令行的那么是不是可以考慮獨(dú)立地執(zhí)行了,只要端口能連接上就可以了。 所以就嘗試將命令行在其他地方進(jìn)行嘗試。
"D:\Program Files\autodesk\3ds Max 2016\python\python.exe" "D:\Program Files\JetBrains\PyCharm 2018.1\helpers\pydev\pydevd.py" --multiproc --qt-support=auto --client 127.0.0.1 --port 55220 --file E:/code/3dsmax/test.py
但是發(fā)現(xiàn)沒(méi)有中斷斷點(diǎn), 這時(shí)候觀察console發(fā)現(xiàn)
Process finished with exit code 0
當(dāng)py文件執(zhí)行完畢后,整個(gè)socket連接就結(jié)束了,這時(shí)候單獨(dú)執(zhí)行命令行,是無(wú)法連接上的。為了避免運(yùn)行結(jié)束可以采用以下方法
- 使py代碼無(wú)法結(jié)束,在文件末尾添加input()
- 在配置pycharm的調(diào)試信息的時(shí)候,發(fā)現(xiàn)“Run with Python Console”選項(xiàng),這個(gè)勾選后,在執(zhí)行完代碼后會(huì)調(diào)用Python控制臺(tái),不會(huì)自動(dòng)退出。具體功能可以看“D:\Program Files\JetBrains\PyCharm 2018.1\helpers\pydev\pydevd.py”這個(gè)文件下的代碼。
通過(guò)綜合比較,發(fā)現(xiàn)配置調(diào)試Run with Python Console比較方便靠譜,在執(zhí)行pycharm調(diào)試后,不要關(guān)閉對(duì)應(yīng)的Console,使用其他地方執(zhí)行命令,也可以順利執(zhí)行斷點(diǎn)。

做了這么多是為了得到一種方法,可以脫離pycharm的調(diào)試入口,進(jìn)行調(diào)試,這樣就可以有機(jī)會(huì)再3dsmax中調(diào)試py代碼。
提高注意力
- 分析命令行,可以將參數(shù)進(jìn)行拆解,
- python執(zhí)行文件的地址
- pycharm提供的pydevd.py文件
- 其他輔助參數(shù)
- socket地址參數(shù)(每次運(yùn)行pycharm調(diào)試都會(huì)變動(dòng))
- 目標(biāo)python文件地址
如果使用其他環(huán)境的Python執(zhí)行的話,只要保留這些參數(shù)應(yīng)該也是可以進(jìn)行調(diào)試的。
- python.ExecuteFile 是否可以支持額外參數(shù)傳入,通過(guò)閱讀幫助文檔,以及測(cè)試,發(fā)現(xiàn)也只能傳入一個(gè)文件的地址。
- python.ExecuteFile 既然無(wú)法傳遞參數(shù),那么我們就把pydevd.py給改造一下,讓他默認(rèn)就有這些參數(shù)的功能,復(fù)制pydevd.py文件為pydevd2.py,修改main函數(shù)
ydevd2.py
def modify_command_args():
f = open(r'E:\code\3dsmax\debugConfig.txt')
s = f.read()
s = s.replace('--cmd-line ', '')
args = sys.argv + s[s.index('-'):].split(' ')
print sys.argv
print args
sys.argv = args
if __name__ == '__main__':
modify_command_args()
main()
debugConfig.txt
"D:\Program Files\autodesk\3ds Max 2016\python\python.exe" "D:\Program Files\JetBrains\PyCharm 2018.1\helpers\pydev\pydevd.py" --cmd-line --multiproc --qt-support=auto --client 127.0.0.1 --port 55220 --file E:/code/3dsmax/test.py
debugConfig.txt 文件中放入命令行,ydevd2.py讀取數(shù)據(jù)并且對(duì)sys.argv進(jìn)行修改,那么運(yùn)行的時(shí)候就默認(rèn)執(zhí)行調(diào)試命令了。
獨(dú)立運(yùn)行一下,發(fā)現(xiàn)可以斷點(diǎn)。
修改 start.ms, 使其運(yùn)行ydevd2.py
python.ExecuteFile @"D:\Program Files\JetBrains\PyCharm 2018.1\helpers\pydev\pydevd2.py"
==使用 MAXScript 運(yùn)行一下,發(fā)現(xiàn)我們可以設(shè)置斷點(diǎn)了,成功了==
問(wèn)題點(diǎn)
- 雖然能調(diào)試,但是發(fā)現(xiàn)每次運(yùn)行完py后,3dsmax就死機(jī)了,或者是再次執(zhí)行start.ms 僅僅返回#success。主要原因,當(dāng)我們命令行中有--cmd-line 時(shí),會(huì)阻塞3dsmax本身的主線程,導(dǎo)致死機(jī),修改方法就是,在參數(shù)傳入的時(shí)候去除該參數(shù) s = s.replace('--cmd-line ', '')。
- 每次執(zhí)行一次,第二次執(zhí)行還是顯示#success,沒(méi)有其他的了,原因不知道,但是在執(zhí)行main()后,添加exit,退出python環(huán)境,這時(shí)候MAXScript會(huì)報(bào)錯(cuò),但是沒(méi)有關(guān)系,我們的連接還在,這時(shí)候,手動(dòng)輸入 python.ExecuteFile @"E:/code/3dsmax/xxx.py" ,就可以繼續(xù)調(diào)試任意的python代碼了。據(jù)此,我們可以專門用start.py進(jìn)行啟動(dòng),然后手動(dòng)調(diào)試我們?nèi)我馊肟?,功能更?qiáng)大了。
圖片.png
剩下的事情
關(guān)于Python插件自動(dòng)化執(zhí)行,以及其他的更豐富的功能,需要慢慢探索,不過(guò)最重要的工具已經(jīng)到手了,其他的就只有發(fā)揮了。

