Are you sure the Python code is fully executing? If you paste that Python code into IDLE shell exactly as-is from that post and hit Enter it probably won’t work. The code has indents at the start of each line, and the “if name” statement at the bottom won’t execute and register the COM server. It has to be run from a file (or remove the “if” and outdent the register command).
Try hitting File/New Window in IDLE and pasting it into the new script window. Fix the indents, save, then run it.
You said:
“It has to be run from a file”
Well I did not copy it exactly, I did fix the indents. But I did copy paste that into the IDLE which “worked”. But your saying it has to be run from a file. I will try opening up the window saving and running.
Thanks,
Ok got it to work.
Steps to make this script work:
Step 1: Download Python Version x.x any version will do I think.
Step 2: Download and install pywin32 which has the win32com python module in it here: http://sourceforge.net/projects/pywin32/
Step 3: Make sure to download the win32com for the python version you have downloaded
Step 4: Open up the Python IDLE Shell and select File\New Window
Step 5: Open up the Python module or create a new one with the Python Com Class code
Step 6: Select from the menu with the Python module the menu Run\Run Module or hit F5
Step 7: Open 3ds Max
Step 8: Open the script editor and run the maxscript code.
My main step missed was the win32com module. I didnt see anyone talking about it here, but I must have missed it.
I’m surprised you did not get an error earlier when trying to import win32com.server.register (looking at the code of post #93).
I am really trying to help build a python community for Max in the hopes they integrate it like Maya and XSI.
I am going to try to post some code snippets and small procedures to keep building interest and a user base.
This is a small script to select the hierarchy of one selected object using vScourge/Volition’s max com setup from GDC.
#import the win32
import win32com.client
#connect to Max
mx = win32com.client.Dispatch('Max.Application')
#start the com in Max
mx._FlagAsMethod('command_from_python')
#create an empty variable to populate the selected object with
mx.command_from_python ('getSel = #()')
#create another max variable to store the hierarchy to call the selction.
mx.command_from_python ('sel = #()')
#populate the variable
mx.command_from_python ('for o in selection do (append getSel o)')
#Currently on works on a single selected object, but query the first selected object
sel= (mx.command_from_python('getSel[1].name'))
#create a python array to store the loops in
lhier = [sel]
def SelHier(obj):
childNum = (mx.command_from_python('$%s.children.count' % obj))
for i in range (childNum):
#since max starts arrays with 1 instead of 0, we need to add one first!
i+=1
child=mx.command_from_python('$%s.children[%i].name' %(obj,i))
lhier.append(child)
SelHier(child)
#call the def to traverse through the hierarchy
SelHier(sel)
#populate the max variable sel
for node in lhier:
mx.command_from_python('append sel $%s' % node)
#select it in max
mx.command_from_python('select (sel)')
#cleanup
del(lhier,SelHier,sel)
This is a nice idea, and I really hope people will go this way. While not a Max user, I have tried to talk people into using Python with Max at work.
Thanks to Adam’s notes, I managed to get work done without having to touch Max. I made a quick script that could convert all our shot cameras to .chan for later use in Nuke (went from two and a half minutes to convert a cam by hand to only a few seconds). This could have been done in Maxscript; but I don’t know Maxscript and none of the processing needed Maxscript per se–and I could use my own Python tools to take care of shot/seq information.
While I really don’t care for Max, it would be neat indeed if Python were properly integrated into it. It just amazes me that all other major apps, closed and open source, have had Python support for years and not Max.
nico
I’m trying to do the first example to create a box from Python. I think the script is failing when it reaches to this point:
win32com.client.Dispatch(“MAX.Application.9”)
I’m using max 2008 though, so I tried changing the 9 to a bunch of variations. I feel stupid for asking but, what would that be for max 2008?
How did you register Max? You should be able to read your registry (w/ ‘regedit’) and find under HKEY_CLASSES_ROOT a key called Max.Application.# (# being 9, 10, etc.) Given the Max history, I guess 2008 would be 10.
In case you did not register Max properly, try Adam Pletcher’s script (can be found under GDC Wrapup on this page). Look under the COM folder.
Hi there!
First of all: Thank you all for this great thread. It helped me VERY much.
I learned how to use a python script in maxscript! yay!
I learned how to send maxscript-commands to 3ds max from python! yay!
(both over COM)
That really helped me out, thx!!!
…but now i’m stuck.
I have a python application (a GUI built with wxPython) and like i said, i can send maxscript-commands to 3ds max. so i can create objects or get all selected objects and things like that. Now i want the gui to update itself if for example in 3dsmax the selection has changed (or on any other event). How can i do that?
I tried to execute a pythonscript from maxscript, which gets an instance of my GUI and executes a method that updates the GUI. 3ds max crashed… i think because 3dsmax was still waiting for a return value when the gui tried to update (and therefore connected to 3dsmax) and BAM! Okay, next thing i tried was using thread to update the GUI asynchronously. Well, 3dsmax didnt crash but nothing happend. At least i dont see anything. I think this approach is a dead end. Perhaps the GUI should poll 3dsmax but that’s not a nice solution, either…
So, how can i send an event from maxscript to a python GUI? Has anyone done something similiar? What’s the (best) solution?
Greetings,
Az
Try creating a COM server inside your Python app, and connecting to it from MaxScript (with createOLEObject). There’s some details on making Python COM servers earlier in this thread. Getting bi-directional COM going in one app can be tricky, but it’s definitely doable.
The last few days i learned much about COM but i’m not sure i got it all right. So if i am mistaken, please correct me!
Links for information to COM:
http://oreilly.com/catalog/pythonwin32/chapter/ch12.html
http://www.zanshu.com/ebook/74_python-programming-on-win32/pythonwin32_snode222.html
The COM Server is called ‘server’, but i think it is a bit misleading, because it only publishes an object that can be used by other processes. You can execute the methods of this object, but it is always a new instance. Btw: The default seems to be that this method runs in the thread you called it from (inProc).
If i call python from maxscript, the class i published per COM is intanciated and i have no way to get the instance of my GUI, except communicating with my GUI thread per inter process communication. For example with the pythonmodule asyncore/asynchat see this link or with a library like pyro or twisted. Right?
But this seems a bit complicated. Starting a pyro server, registering a PythonCom server, calling the pythoncomserver in maxscript that then calls the pyro server which then triggers an event in the GUI…
Is this the way to go?
I didn’t find anything about establishing a connection from maxscript directly.
One thing makes me wonder though:
If i send a command to maxscript from python (using the maxscriptcode in the first post of this thread), it is like sending a command to a server. But how does it work? This direction is so easy, why is the direction back to a python GUI so complicated?
I feel like i missed something. Some option that i can set when registering the pythoncom server, so everything works like i want it to.
If i get it working, i hope i can post a minimalistic example here to contribute something usefull to this thread.