Python + MXS


#241

checkout the “[b][b]SafeArrayWrapper” class in MaxScript. I’ve passed arrays that way…

[/b][/b]


#242

Again, I’m no wiz’ at this, but I believe you can get the content of a MaxArray to Python and work with it: myPyContainer = conn.MaxDo(‘myMaxArray’). I say container because I “think” you will get a tuple, not an array. You should be able to then loop through it, or even change it to an array for your needs.


#243

Yes, you’ll get arrays back as tuples, as long as they contain data types supported by COM, or you put a convert-to-string function in front of it like the script I posted above.

I’ve also noticed Max will cause COM to throw an error if the array its sending is empty. The script I posted above gets around this by checking before returning the value, and sending a special string back to Python you can then turn into an empty list, tuple, etc.


#244

True. I need to clarify that anything I have posted is based on the scripts provided by Adam. Definitively a life safer.

While I’m at it, anyone has noticed rounding issues between Max and Python? In my example, I was converting cameras to .chan. I noticed that the precision of the decimal values where different (around the 4th or 5th number). I compared the output from the original Maxscript and my script where I tried to do the manip in Python, and I got different numbers. In the end, I just did the manip of the numbers inside Max and passed the value back to Python.


#245

You mean stuff like this?

>>> 18.49 * 100
1848.9999999999998
>>> 0.1
0.10000000000000001

Most languages (machines, actually) work this way, but some sorta hide it more than others. MaxScript, for instance, is a little less obvious about it. Here’s a somewhat long explanation:

http://docs.python.org/tutorial/floatingpoint.html


#246

Thanks guys! Here is a snippet to return selected objects to python, not pretty, but moving in the correct direction.

*This is using vScourge lovely Max COM


 import win32com.client
 mx = win32com.client.Dispatch('Max.Application')
 mx._FlagAsMethod('command_from_python')
 mx.command_from_python ('myArray = #()')
 mx.command_from_python ('for o in selection do (append myArray o)')
 nArray= (mx.command_from_python('myArray'))
 for i in nArray:
 	print i
 

Unfortunately my Maxscripting is very very weak. I am a Maya/Mel scripter with some good knowledge in Python, and this new project requires maxscripting so I am trying to avoid completely learning a new language if possible!


#247

Hi! I am interested in using Python in Max. I am trying to get the example in the first post to work.

I run the MaxScript, and it returns “OK”. So that’s okay.

Then I run the Python script, and it runs, nothing happens. No box appears in Max… but no errors either… it blinks briefly and then it just goes onto the next line ready for another entry.

I’ve never used Python before, am I doing something wrong?

I’m on XP, using Python 2.6.1 with the win32 module it says you need, and Max 9 with SP2.

Thanks!


#248

Could you show us the Max and Python code you are running? That could help us see what you might be missing.

You mentioned being new to Python. There is a lot of learning material outthere, but it also can be too much to look at for a newcomer. Do you have a background in scripting or programming in a different language? Based on this, we could give you a few pointers to what resources could help you learn Python.

Cheers. nico


#249

[b]
It’s a copy of the code from the first post with the comments removed:

The Max part, which when run, returns “OK”:[/b]

fn DoSomething obj = ( try(
[indent] execute obj
[/indent][indent] return true
[/indent] )catch(
[indent] return false
[/indent][indent] )
[/indent] )
registerOLEInterface #(DoSomething)

The python part, which throws no errors, but fails to do anything:

import win32com.client

conn = win32com.client.Dispatch(“MAX.Application.9”)

conn._FlagAsMethod(“DoSomething”)

conn.DoSomething(“Box()”)


I know quite a bit of MEL and some C++. I also know a little MaxScript. I’d say I’m probably an intermediate user. I understand how code works, and can look up things if I don’t know them. The weird thing about Python is the use of indenting as a way of demarcating code blocks, as opposed to using parenthesis, etc. I’m not indenting any of the lines in the Python part, and I don’t know if maybe I’m missing something, or maybe I’m not running it the right way in the Idle interface? I type it in, and hit return, but it doens’t do anything. I’ve managed to get some simple code (i.e. “hello world” type stuff) to work in Python. So, I don’t know :smiley:


#250

Could someone delete this… Sorry, Thank you.


#251

I copied and pasted your code, with the exception of the MAX.Application version, and everything worked fine.

Have your registered Max properly? Adam has shared some great code that does it for you - and other things (I like his code as it allows you to share data between Max and Python). Look up his page and download the zip file and look under 6_COM:
http://techarttiki.blogspot.com/2008/03/gdc-wrap-up.html

As for learning Python, if you have experience with other languages, why not start with the official Python docs/tutorial, and look up some of the online books. Dive Into Python is fun if you already know how to code, and I also like the O’Reilly books. I’m not a programmer myself, but I like to learn by looking at people’s code as well. Online forums are a good place for this.


#252

Forgive me for my ignorance guys. I use Python in Maya and used maxscript for years but have yet to try Python in Max. I am trying to get the code on post 93 to work link here:

http://forums.cgsociety.org/showpost.php?p=4686517&postcount=93

The python and maxscript works. But I am not clear on how I am to execute this process. I have Python 1.6 installed now. I opened up 3ds max and I opened up the IDLE Python Shell. I copy/paste the Python code into the Shell which executes with no errors.

Then in max I run the maxscript portion. Which prints this:

GetComObj()
“error create ole object”
Rollout:pyprompt
“error create ole object”
true

I type this into the top portion of the UI:

foo = 10

And I press the submit button. And now it errors and prints this:

GetComObj()-- Error occurred in btn_submit.pressed()
– Frame:
– t: undefined
>> MAXScript Rollout Handler Exception: – Unknown property: “RunCom” in false <<

“error create ole object”
Rollout:pyprompt
“error create ole object”
true

What am I doing wrong?


#253

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.


#254

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,


#255

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.


#256

I’m surprised you did not get an error earlier when trying to import win32com.server.register (looking at the code of post #93).


#257

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)



#258

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


#259

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? :smiley:


#260

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.