3dsmax 2015 版本之后开始支持python,使用MAXScript可以跳转到python文件的执行
python.ExecuteFile @"C:\Program Files\Autodesk\3ds Max 2015\scripts\Python\demoBentCylinder.py"
对于我这种E文不好、python不好、3dsmax也不好的“三不好青年”,来完成插件开发,那可真是废了事情了。一直写惯了静态语言,并且有强大开发环境支持,代码提示+调试+重构,没有这三个利器,简直寸步难行,为此,就来一一解决这些问题,记录了探索的过程。
查阅历史
百度谷歌搜寻一遍,找一下python开发3dsmax的信息,发现啥都没有,仅有的一些就告诉你,如何通过ms来执行python文件,以及官方的帮助文档,官方文档告诉你api,但是如何顺畅地搭建开发调试环境没有任何说明。
官方可用文档2016:https://pan.baidu.com/s/1QAtOARo07zSzLqDnfPBeOg
提取码:j6tj
材料
- 3dsmax 2016
- pycharm
创建项目
使用pycharm 创建纯的python项目,==目录不要带有空格==, python环境使用3dsmax安装目录下自带的python,{软件安装目录}\autodesk\3ds Max 2016\python\python.exe
解决代码引用和提示问题
插件API都是从 MaxPlus 这个模块入手的,我们自己写的代码就得 import MaxPlus,发现直接导入的时候,IDE提醒找不到对应的模块,也就没有什么代码提示了和查阅了,==所以第一步就是要找到MaxPlus的接口python文件==
在3dsmax安装目录下搜索 “maxplus”,发现有对应可用的py文件
将MaxPlus.py文件拷贝到我们的项目文件下,这样自己写的代码就可以直接导入MaxPlus,并且可以随时查看源码。
编写代码并且执行
- 启动3dsmax的maxscript的执行环境。
- 菜单->Scripting->MAXScript Listener
-
菜单->Scripting->MAXScript Editor
- 项目建立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
- 项目中建立start.ms, 用来启动python, 其实也可以每次手动输入
start.ms
python.ExecuteFile @"E:/code/3dsmax/test.py"
其中test.py文件地址自己替换。
- 执行
使用MAXScript Listener 菜单 file->run script 执行项目目录下的start.ms, 观察结果,可以在3dsmax中添加一个圆柱体
解决调试问题
不能调试的代码,开发效率至少也得下降一半,除非是大神级别,并且把单元测试给补全了,一般人就是依赖调试工具,才能迅速定位问题点。
没有调试的支持
编码五分钟,log一小时, 加班一整夜。
反之
编码一小时,调试五分钟, 收工。
当我们使用pycharm进行python调试的时候,发现console会打印
"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
第一行是一个执行命令, 第二行是debugger进行socket连接,第三行是连接成功,第四行是py文件的执行打印。
调试的过程可以推测为:
- 使用pydevd.py创建调试环境,执行目标文件,并且与当前pycharm进行socket连接
- 连接成功,传输断点信息,以及执行过程
既然是命令行的那么是不是可以考虑独立地执行了,只要端口能连接上就可以了。 所以就尝试将命令行在其他地方进行尝试。
"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
但是发现没有中断断点, 这时候观察console发现
Process finished with exit code 0
当py文件执行完毕后,整个socket连接就结束了,这时候单独执行命令行,是无法连接上的。为了避免运行结束可以采用以下方法
- 使py代码无法结束,在文件末尾添加input()
- 在配置pycharm的调试信息的时候,发现“Run with Python Console”选项,这个勾选后,在执行完代码后会调用Python控制台,不会自动退出。具体功能可以看“D:\Program Files\JetBrains\PyCharm 2018.1\helpers\pydev\pydevd.py”这个文件下的代码。
通过综合比较,发现配置调试Run with Python Console比较方便靠谱,在执行pycharm调试后,不要关闭对应的Console,使用其他地方执行命令,也可以顺利执行断点。
做了这么多是为了得到一种方法,可以脱离pycharm的调试入口,进行调试,这样就可以有机会再3dsmax中调试py代码。
提高注意力
- 分析命令行,可以将参数进行拆解,
- python执行文件的地址
- pycharm提供的pydevd.py文件
- 其他辅助参数
- socket地址参数(每次运行pycharm调试都会变动)
- 目标python文件地址
如果使用其他环境的Python执行的话,只要保留这些参数应该也是可以进行调试的。
- python.ExecuteFile 是否可以支持额外参数传入,通过阅读帮助文档,以及测试,发现也只能传入一个文件的地址。
- python.ExecuteFile 既然无法传递参数,那么我们就把pydevd.py给改造一下,让他默认就有这些参数的功能,复制pydevd.py文件为pydevd2.py,修改main函数
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读取数据并且对sys.argv进行修改,那么运行的时候就默认执行调试命令了。
独立运行一下,发现可以断点。
修改 start.ms, 使其运行ydevd2.py
python.ExecuteFile @"D:\Program Files\JetBrains\PyCharm 2018.1\helpers\pydev\pydevd2.py"
==使用 MAXScript 运行一下,发现我们可以设置断点了,成功了==
问题点
- 虽然能调试,但是发现每次运行完py后,3dsmax就死机了,或者是再次执行start.ms 仅仅返回#success。主要原因,当我们命令行中有--cmd-line 时,会阻塞3dsmax本身的主线程,导致死机,修改方法就是,在参数传入的时候去除该参数 s = s.replace('--cmd-line ', '')。
- 每次执行一次,第二次执行还是显示#success,没有其他的了,原因不知道,但是在执行main()后,添加exit,退出python环境,这时候MAXScript会报错,但是没有关系,我们的连接还在,这时候,手动输入 python.ExecuteFile @"E:/code/3dsmax/xxx.py" ,就可以继续调试任意的python代码了。据此,我们可以专门用start.py进行启动,然后手动调试我们任意入口,功能更强大了。
剩下的事情
关于Python插件自动化执行,以及其他的更丰富的功能,需要慢慢探索,不过最重要的工具已经到手了,其他的就只有发挥了。