CGTalk > Software > Autodesk 3ds max > 3dsMax SDK and MaxScript
Login register
reply share thread « Previous Thread | Next Thread »
 
Thread Tools Search this Thread Display Modes
Old 10-02-2007, 09:05 PM   #91
Chris
Chief time waster
 
Chris's Avatar
portfolio
Chris Williamson
3D / Motion Graphics Artist
Weta Workshop
Wellington, New Zealand
 
Join Date: Dec 2001
Posts: 1,412
So using Com, would there be a way to pass a bitmap object to max somehow? or would the best method be to open a PIL image, convert it to an array, pass that to max & use set pixels or something to recreate an bitmap? I'm guessing that would be fairly slow...
__________________
--------------------------------
animationsbychris.com
 
Old 10-02-2007, 11:48 PM   #92
specxor
Frequenter
portfolio
David Mackenzie
Technical Director
Sydney, Australia
 
Join Date: Feb 2005
Posts: 122
Hi Chris,

That would work just fine but as you rightly pointed out it would be pretty slow, other alternatives would be to just parse the path to the image to max and open it that way. I guess it depends on what you doing, you could also use PIL to save a temp image and then parse the temp file path to max...

Cheers
Dave
 
Old 10-03-2007, 03:00 AM   #93
specxor
Frequenter
portfolio
David Mackenzie
Technical Director
Sydney, Australia
 
Join Date: Feb 2005
Posts: 122
PyInterp

Hi Guys,

This is a little script I quickly through together for a mate and thought some of you might like it. You can parse commands from max to python and have the tracbacks and stdout returned to you.

Here is a simple example:
http://forums.cgsociety.org/attachm...id=118728&stc=1


Here is an example of a traceback:
http://forums.cgsociety.org/attachm...id=118729&stc=1

Anyways time for some code:
here is the python code:
Code:
""" Simple Com Class for parsing commands to the python. Will return sys.stout or in the event of a exception, it will catch the error and return the traceback. Crafted By David Mackenzie Notes: - If you get a error in max that is something like "Cannot create instance of (com class) try registering the Com Class from a admin account. - This is just a hack, so if for some reason your computer self destructs its not my fault. """ import sys import os import win32com.server.register Writing = True def TBWrite(): """Returns the traceback as a string, VERY handy dandy biatch""" import traceback return traceback.format_exc() #Catch sys.stdout, this is what would normaly be returned to the screen by python class CatchOut: def __init__(self, obj): """obj requires the method COut""" self.Obj = obj def write(self, data): """This method catches sys.stdout, stdout expects a write method""" self.Obj.COut(data) #global Writing #Writing = False class MXSPrompt: _public_methods_ = [ 'RunCom' ] _reg_progid_ = "DaveTools.MXSPrompt" _reg_clsid_ = '{CF24CDE3-680B-4A38-82E0-958C57921AF7}' def __init__(self): self.Buffer = "" self.StdOut = CatchOut(self) #sys.stderr = self.StdOut sys.stdout = self.StdOut def RunCom(self, commstr): """Method that is visible to COM""" try: global Writing self.Buffer = "" exec commstr """ while(Writing): pass Writing = True """ return self.Buffer except: return TBWrite() def COut(self, dstr): """Just Updates the Buffer""" self.Buffer = self.Buffer + dstr if __name__ == "__main__": win32com.server.register.UseCommandLine(MXSPrompt)


And now for the max code:

Code:
/* Just a quick hack to demonstraight some python in max. This is a very script on both ends. If there is any interest I will develop it further. crafted by, David Mackenize Notes: -Any strange errors, python or max please send to me. -I would recomend, where ever you would like to place a tab insert 4 'spaces' -You might find that if you have 2 or more Dialogs open (of this script) the previous ones will drop/loose there connection with COM. Cheers Dave */ fn GetComObj = ( try( o = createOLEObject "DaveTools.MXSPrompt" return o )catch( print "error create ole object" return False ) ) rollout pyprompt "Python Prompter" ( group "Py Prompt" ( edittext py_out "" height:125 edittext py_in "" height:150 ) button btn_submit "Submit" align:#right local obj = GetComObj() on btn_submit pressed do( t = obj.RunCom py_in.text py_out.text = t ) ) createDialog pyprompt 450 350



Cheers
Dave
Attached Images
File Type: jpg Fun.jpg (63.9 KB, 219 views)
File Type: jpg Traceback.jpg (57.1 KB, 176 views)
Attached Files
File Type: zip PyInterp.zip (125.3 KB, 50 views)
 
Old 10-19-2007, 06:00 AM   #94
specxor
Frequenter
portfolio
David Mackenzie
Technical Director
Sydney, Australia
 
Join Date: Feb 2005
Posts: 122
Python + MySQL

Hi Guys,

A couple people following the thread have asked about some database code, I did have some stuff I wrote ages ago, which for whatever reason has seemingly disappeared from my hard drive! None the less I had been promising to post some code for a long time, I finally got off my ass and wrote some new stuff...

So here a really simple class to demo straight saving maxfiles to (or any data for that matter) to a database (I was using MySQL i have tested the code with anything else).

I will post a com version later tonight.... anyways enough jibba jabba here is the code, if you get any errors just post them or pm me and yes I was lazy and did not comment my code I will fix this later though...

Cheers
Dave

Code:
""" Demo Class showing interaction with MySQLdb. The Class assumes there is db called 'mymaxfiles' and that it has a table called 'maxfiles'. Its just a basic example of how one my want to store some files etc... All the methods below assume the database mymaxfile exists as well. Crafted By, David Mackenzie First off I don't pretend to be some SQL hacker! I just know what I need to.... This is a simple class for interacting with simple db and table. It could easily be modified to do allot more. You will also require MySQLdb for this to work you can download here "http://sourceforge.net/projects/mysql-python". I should also point out that I have not debugged this a great deal, I have however had no errors thrown in all my testing, if you do get an error just shoot it acrros to me... Cheers Dave """ import MySQLdb as mys import os import os.path as pt def InsertMaxFile(thefile): db = mys.connect(host="localhost", user="root", passwd="daveRoot", db="mymaxfiles") mycurs = db.cursor() mycurs.execute("INSERT INTO maxfiles (files) values('%s')" % (thefile)) db.commit() return True def CreateTable(self): try: db = mys.connect(host="localhost", user="root", passwd="daveRoot", db="mymaxfiles") mycurs = db.cursor() db.commit("CREATE TABLE maxfiles (id INT NOT NULL AUTO_INCREMENT, files varchar(256) NOT NULL, primary key(id));") return True except: return [False, TBWrite()] def TBWrite(): import traceback return traceback.format_exc() class MaxFileSaver: def __init__(self, server, username, password, database): try: self.db = mys.connect(host=server, user=username, passwd=password, db=database) self.Cursor = self.db.cursor() self.Connected = True self.Commited = True except: self.Connected = False self.db = None self.Cursor = None self.Commited = True print TBWrite() def InsertFile(self, thefile): if self.Connected == True: try: self.Cursor.execute("INSERT INTO maxfiles (files) values('%s')" % (thefile)) self.Commited = False return True except: return [False, TBWrite()] else: return [False, "Something went wrong"] def CommitChanges(self, yayorney): if self.Connected: if yayorney == True: try: self.db.commit() self.Commited = True return True except: self.Commited = False return [False, TBWrite()] else: return [False, "Not Connected"] def GetFiles(self): if self.Connected: try: self.Cursor.execute("SELECT * FROM maxfiles") return (self.Cursor.fetchall()) except: return [False, TBWrite()] def SetFile(self, theid, thevalue): if self.Connected: try: print self.Cursor.execute("UPDATE maxfiles\nSET files='%s' WHERE id='%s'" % (thevalue, theid)) return True except: return [False, TBWrite()] else: return [False, "Not Connected"] def DeleteFile(self, theid): if self.Connected: try: self.Cursor.execute("DELETE FROM maxfiles WHERE id=%s" % (theid)) return True except: return [False, TBWrite()] else: return [False, "Not Connected"] def RollBackChanges(self, yayorney): if self.Commited == True: return [False,"Data already commited, better luck next time"] if self.Connected: if yayorney: try: self.db.rollback() return True except: return [False, TBWrite()] else: return [False, "Not Connected"] def ReConnect(self, server, username, password, database): self.Connected = False self.db = None self.Cursor = None self.Commited = True try: self.db = mys.connect(host=server, user=username, passwd=password, db=database) self.Cursor = self.db.cursor() self.Connected = True except: return [False, TBWrite()] if __name__ == "__main__": con = MaxFileSaver("localhost", "root", "daveRoot", "mymaxfiles") print con.InsertFile("C:\\\\With Any luck this will work.max") print con.CommitChanges(True) for i in con.GetFiles(): print i print con.DeleteFile("14") print con.SetFile("23", "C:\\\\SomeNewFile") print con.CommitChanges(True)
Attached Files
File Type: zip MSQLDEMO.zip (1.5 KB, 16 views)
 
Old 10-22-2007, 12:46 PM   #95
specxor
Frequenter
portfolio
David Mackenzie
Technical Director
Sydney, Australia
 
Join Date: Feb 2005
Posts: 122
Hi guys,

Just wrote a new com class for MySQL connections. It works well and is simple to implement.

Here is the code:

Code:
""" MySql com class, provides basic connection to MySQL across com. Crafted By, David Mackenzie Notes: -All errors are handled, if an exception is caught, a list is returned as [False, the traceback] -Requires MySQLdb, http://sourceforge.net/projects/mysql-python -If you get any tracebacks please post them or send them to me! -I pulled this code from a larger implementation im working on so there may be some bugs, although there should not. Max Usage: >> a = createOLEObject "DavesTools.ComSql" <OLEObject:DavesTools.ComSql> >> a.Connect "localhost" "root" "daveRoot" "mymaxfiles" true >> a.Execute("SELECT files FROM maxfiles WHERE id=3") true >> a.Fetch() SafeArrayWrapper #("Somemaxfile.max") #(0) """ import MySQLdb as mys import traceback class ComSql: """Com interface for parsing SQL commands.""" _public_methods_ = ['GetCommited', 'GetConnected', 'Connect', 'Execute', 'Fetch', 'RollBack', 'Commit'] _reg_progid_ = 'DavesTools.ComSql' _reg_clsid_ = '{3B165F3B-6E90-4E1B-AA34-D6B3E51C9115}' def __init__(self): self.Connected = False self.Commited = True self.Cursor = None self.db = None def GetCommited(self): return self.Commited def GetConnected(self): return self.Connected def Connect(self, server, username, password, database): """Connect to the database""" try: self.db = mys.connect(host=server, user=username, passwd=password, db=database) self.Cursor = self.db.cursor() self.Connected = True self.Commited = True return True except: self.Connected = False self.Commited = True self.Cursor = None self.db = None return [False, self.__sqlerror()] def Execute(self, command): """Execute the parsed command.""" if self.Connected: try: self.Cursor.execute(command) self.Commited = False return True except: return [False, self.__sqlerror()] else: return [False, "Not Connected"] def Fetch(self): """Return Data from the db, the appropiate command should had have been parsed to execute before hand""" if self.Connected: try: return self.Cursor.fetchall() except: return [False, self.__sqlerror()] else: return [False, "Not Connected"] def RollBack(self): """Roll back any un-commited changes""" if self.Commited: return [False, "Data already commited"] else: if self.Connected: try: self.db.rollback() return True except: return [False, self.__sqlerror()] else: return [False, self.__sqlerror()] def Commit(self): """Commit changes to database""" if self.Connected: try: if self.Commited == False: self.db.commit() self.Commited = True return True except: return [False, self.__sqlerror()] else: return [False, self.__sqlerror()] def __sqlerror(self): return traceback.format_exc() if __name__ == "__main__": TESTING = False if TESTING: print "Testing\n" con = ComSql() print "Connect:\n\t", con.Connect("localhost", "root", "daveRoot", "mymaxfiles") print "Execute:\n\t", con.Execute("INSERT INTO maxfiles (files) values('C:\\\\SomeNewFile.max')") print "Commint:\n\t", con.Commit() print "Execute:\n\t", con.Execute("SELECT * FROM maxfiles") print "Fetching:\n\t", con.Fetch() print "\nDone" else: print "Registering COM server..." import win32com.server.register win32com.server.register.UseCommandLine(ComSql)


Cheers
Dave
 
Old 11-06-2007, 12:01 AM   #96
TheIvIaxx
rm -rf /
 
TheIvIaxx's Avatar
portfolio
Brett Dixon
Sr Technical Artist
Irvine, USA
 
Join Date: May 2004
Posts: 500
I'm getting some wierd garbage collection errors when pairing python and max. So my script basically sends the "loadmaxfile" command with a file, max opens it, run a maxscript on it, and return a list of strings. then moves on to another file. simple enough right?

Well after about 3-4 files, max throws this wierd error:

"Unknown error occured during garbage collection. If you see this message frequently, restart max." or something to that extent. I put the gc() in my maxscript hoping that would fix it, but no luck.

Am i not doing something here? My python stuff is pretty simple:

Code:
pyMax = win32com.client.Dispatch("MAX.Application.8") pyMax._FlagAsMethod("loadMaxFile") pyMax._FlagAsMethod("RenderItem") ... for z in names: print "Building object..." newItem = item(z) print "Object built, Loading into max..." try: pyMax.loadMaxFile("Z:\XXX" + z.replace("/", "\\")) except pywintypes.com_error, e: print e[1] print "Rendering Item..." renderedItems = [] try: renderedItems = pyMax.RenderItem() newItem.dbInsert(renderedItems) except pywintypes.com_error, e: print e[1] print "Success, moving on..."


"item()" is a python object which does some DB stuff.
"RenderItem()" is the maxscript being run.

Thanks
__________________
"When sales determine status, I hold no faith in the majority" -El P

Draenei:Thread
Troll:Thread
 
Old 11-06-2007, 12:39 AM   #97
RustyKnight
Lord of the posts
Shane Whitehead
Technical Artest/Sys Admin/Tools Developer
01 Animation
Frankston, Australia
 
Join Date: May 2007
Posts: 626
Quote:
Originally Posted by TheIvIaxx
I'm getting some wierd garbage collection errors when pairing python and max. So my script basically sends the "loadmaxfile" command with a file, max opens it, run a maxscript on it, and return a list of strings. then moves on to another file. simple enough right?

Well after about 3-4 files, max throws this wierd error:

"Unknown error occured during garbage collection. If you see this message frequently, restart max." or something to that extent. I put the gc() in my maxscript hoping that would fix it, but no luck.

Am i not doing something here? My python stuff is pretty simple:

Code:
pyMax = win32com.client.Dispatch("MAX.Application.8") pyMax._FlagAsMethod("loadMaxFile") pyMax._FlagAsMethod("RenderItem") ... for z in names: print "Building object..." newItem = item(z) print "Object built, Loading into max..." try: pyMax.loadMaxFile("Z:\XXX" + z.replace("/", "\\")) except pywintypes.com_error, e: print e[1] print "Rendering Item..." renderedItems = [] try: renderedItems = pyMax.RenderItem() newItem.dbInsert(renderedItems) except pywintypes.com_error, e: print e[1] print "Success, moving on..."


"item()" is a python object which does some DB stuff.
"RenderItem()" is the maxscript being run.

Thanks
I had a simular issue recently (not with the com bridge, but with max). I may be totally off the mark, but...it may have something to do with the inital heap settings for maxscript.

Go to Customize -> Preferences -> Maxscript (tab) and increase the maxscript memory to a larger amount...about 60-70meg should do the trick. Then try again.

At least you will know if it is a max issue or a com issue pretty quickly.

Also, play around the amount of memory as well till you find a setting you are comfortable with.

Hope it helps
Shane
__________________
If it's worth doing, it's worth scripting
Don't wish for this to be eaiser, wish for you to better
 
Old 11-06-2007, 09:08 AM   #98
specxor
Frequenter
portfolio
David Mackenzie
Technical Director
Sydney, Australia
 
Join Date: Feb 2005
Posts: 122
Hi Brett,

I have a similar setup for keeping asset library's in order, which essentially recursively goes through a library and updates the database where it needs to. I did notice that the machine I run it on has the max script heap size set to 128mb, so maybe Shane is on to something, I might try lowering the heap size and see what happens.

I'm interested to here how you go...

Cheers
Dave
 
Old 11-06-2007, 05:57 PM   #99
TheIvIaxx
rm -rf /
 
TheIvIaxx's Avatar
portfolio
Brett Dixon
Sr Technical Artist
Irvine, USA
 
Join Date: May 2004
Posts: 500
ok, i set it to 128mb and it seemed to work pretty good. Due to some bugs with my script it will sometimes blow up max. But upping the heap size let me get through 12+ without issue which is way more than before. I will keep tweaking it and let you know what i find.

Thanks again
__________________
"When sales determine status, I hold no faith in the majority" -El P

Draenei:Thread
Troll:Thread
 
Old 11-06-2007, 11:28 PM   #100
TheIvIaxx
rm -rf /
 
TheIvIaxx's Avatar
portfolio
Brett Dixon
Sr Technical Artist
Irvine, USA
 
Join Date: May 2004
Posts: 500
OK, so i removed the gc() call in my script and upped my heap to 256MB and its working much better now. Thanks for the help guys.
__________________
"When sales determine status, I hold no faith in the majority" -El P

Draenei:Thread
Troll:Thread

Last edited by TheIvIaxx : 11-07-2007 at 02:09 AM. Reason: resolved...kinda
 
Old 12-18-2007, 11:59 AM   #101
lechoo
Frequenter
 
lechoo's Avatar
 
Join Date: May 2004
Posts: 117
What should I do if I have two instances of 3ds max launched, I want to control one of them with python and choose which one? Right now only max that was started first works as COM Server.
__________________
Pixel Factory
 
Old 12-19-2007, 04:41 AM   #102
ehulser
Developer
Eric Hulser
CEO/Lead Developer
Proejx Software, LLC
Palo Alto, USA
 
Join Date: May 2003
Posts: 200
Embedded Python for MAXScript

Hey guys,

I just finished up the first version of this DLL for 3dsMax (still pretty rough) that we're going to start using here at Blur...pretty much it embeds python for use inside of MAXScript, opening up all the modules that exist in python directly. There are some example scripts on how its used, but its relatively simple - you import your module, and work with with it as if you were in python.

re = python.import "re"
m = re.match "[a-zA-Z]*" "Test test test"
if ( m != undefined ) then ( print (m.group()) ) -- prints "Test"

etc.

More examples in the DLL. We're working (still) on getting BlurBeta running where everything will be open source, but until that gets up, I have the *.zip file with the DLL and would love some feedback on how its working, just no where to throw the zip. If anyone has a mirror, I can email the file to you and upload it so others can download. Otherwise, email me if you want the DLL and I'll send it to you.

Thanks!

Eric Hulser
eric@blur.com
Tools Developer
Blur Studio
 
Old 12-19-2007, 10:20 AM   #103
martinB
TD
 
martinB's Avatar
portfolio
Martin Breidt
Tuebingen, Germany
 
Join Date: Aug 2007
Posts: 272
Quote:
Originally Posted by ehulser
I just finished up the first version of this DLL for 3dsMax (still pretty rough) that we're going to start using here at Blur...pretty much it embeds python for use inside of MAXScript, opening up all the modules that exist in python directly.


That is pretty cool! I can wait for your final release but if that is out, make sure to let us know! Directly connecting Python to MAXScript will make a bunch of people very happy over here.

Cheers!
-- MartinB
 
Old 12-19-2007, 12:27 PM   #104
ypuech
Lord of the posts
portfolio
Yannick Puech
Software Engineer
Solid Angle SL
Madrid, España
 
Join Date: Jun 2005
Posts: 552
Quote:
Originally Posted by ehulser
I just finished up the first version of this DLL for 3dsMax (still pretty rough) that we're going to start using here at Blur....pretty much it embeds python for use inside of MAXScript

Being able to use Python inside Max is a great new stuff and will make me learn Python much faster!

Quote:
Originally Posted by ehulser
If anyone has a mirror, I can email the file to you and upload it so others can download. Otherwise, email me if you want the DLL and I'll send it to you.

You can contact David Baker of maxplugins.de (he is on CGtalk forums). He can offer a subdomain with space to host your plugins and web stuff for free.
__________________
 
Old 12-19-2007, 08:09 PM   #105
PEN
R&D/Technical Director
 
PEN's Avatar
portfolio
Paul Neale
PEN Productions
Canada
 
Join Date: Jun 2002
Posts: 7,417
Not sure if this is going to create a double post, if so please delete.

If you want I can put it on on http://paulneale.com, just mail it to
paul@paulneale.com

Quote:
Originally Posted by ehulser
Hey guys,

I just finished up the first version of this DLL for 3dsMax (still pretty rough) that we're going to start using here at Blur...pretty much it embeds python for use inside of MAXScript, opening up all the modules that exist in python directly. There are some example scripts on how its used, but its relatively simple - you import your module, and work with with it as if you were in python.

re = python.import "re"
m = re.match "[a-zA-Z]*" "Test test test"
if ( m != undefined ) then ( print (m.group()) ) -- prints "Test"

etc.

More examples in the DLL. We're working (still) on getting BlurBeta running where everything will be open source, but until that gets up, I have the *.zip file with the DLL and would love some feedback on how its working, just no where to throw the zip. If anyone has a mirror, I can email the file to you and upload it so others can download. Otherwise, email me if you want the DLL and I'll send it to you.

Thanks!

Eric Hulser
eric@blur.com
Tools Developer
Blur Studio
__________________
Paul Neale
http://paulneale.com
 
reply share thread


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
CGSociety
Society of Digital Artists
www.cgsociety.org

Powered by vBulletin
Copyright ©2000 - 2006,
Jelsoft Enterprises Ltd.
Minimize Ads
Forum Jump
Miscellaneous

All times are GMT. The time now is 10:47 AM.


Powered by vBulletin
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.