<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>duber's blog &#187; Python</title>
	<atom:link href="http://blog.duber.cz/category/python/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.duber.cz</link>
	<description>the official duber studio™ blog</description>
	<lastBuildDate>Thu, 22 Jul 2010 15:53:28 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>duberPython features demonstration!</title>
		<link>http://blog.duber.cz/3ds-max/duberpython-features-demonstration</link>
		<comments>http://blog.duber.cz/3ds-max/duberpython-features-demonstration#comments</comments>
		<pubDate>Thu, 04 Mar 2010 15:16:28 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=457</guid>
		<description><![CDATA[
I&#8217;m trhilled to be able to finally showcase, at least, some of our very own Python implementation into 3ds Max!
First off, our primary reason for writing our own, proprietary, Python connection to 3ds Max is Tactic by Southpaw Technology. An awesome asset management system entirely written in Python that I decided to invest in and [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://blog.duber.cz/wp-content/uploads/duberpython_banner.png' alt='duberPython banner' /></p>
<p>I&#8217;m trhilled to be able to finally showcase, at least, some of our very own Python implementation into 3ds Max!</p>
<p>First off, our primary reason for writing our own, proprietary, Python connection to 3ds Max is <a href="http://southpawtech.com/tactic.html">Tactic by Southpaw Technology</a>. An awesome asset management system entirely written in Python that I decided to invest in and integrate our tools and software packages into. Another reason for this connection, later came up, was the need for writing much more complex scripts with complex GUIs, since, as you probably know, a few functional lines of code are hardly enough in a modern, efficient, VFX production of today. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>The heart of our Python integration is <a href="http://www.microsoft.com/NET/">dotNET from Microsoft</a>. I can&#8217;t express myself enough how much I appretiate this framework! The brain of our Python integration is <a href="http://www.ironpython.net/">IronPython</a>. Also a product from Microsoft, completely open source and free, which are two very important aspects for any pipeline tool in any production facility of any size. Not the price as much as the availability of the software. And with IronPython and Microsoft, I am certain that this piece of software will be around for years!</p>
<p><span id="more-457"></span></p>
<p>So, what have we done?</p>
<ul>
<li>We&#8217;ve developed a bridge that connects MAXScript and Python via dotNET.</li>
<li>The bridge converts most of native Python and MAXScript data types to and from one another.</li>
<li>We&#8217;ve implemented several, custom, methods in Python that allow us to directly communicate with 3ds Max via MAXScript.</li>
<li>We&#8217;ve also implemented error reporting so that when an error is thrown in Python, it&#8217;ll return the exception in MAXScript for debuging.</li>
<li>Everything is based on dotNET and written in C#.</li>
<li>The best part? Our Python bridge is completely platform and 3ds Max version independent!</li>
</ul>
<p>Let me talk about the custom Python methods first. We&#8217;ve incorporated a class called <strong>mxsCon</strong>, that stores several methods for direct communication with 3ds Max as well as a variable<br />
that stores passed arguments from MAXScript to Python for greater flexibility, especially when executing short code snippets.</p>
<p>The initial design meant to provide a way of directly running Python code from within MAXScript. However, with more complex tools needed nowdays, this proved to be insufficient and thus we&#8217;ve developed a way of executing more complex Python scripts written externally using IronPython. This works perfectly well if you plan on using 3ds Max&#8217;s interpreter and just want to pass values around MAXScript and Python. This is perfectly efficitent and enough for writing really complex tools based on Python. In our case, it&#8217;s the connection to Tactic.</p>
<p>However, later, it occured to me that since we have most of the hard work done, why not bring everything over to the Python side. Since Python is such a great and powerful language, why bother with MAXScript! So we developed another method for executing MAXScript code directly within Python scripts and have the result, evaluated in MAXScript, be passed back to Python. IronPython that is. Since all the value conversions had already been done, this proved to be an extremely powerful and efficient way of writing very complex tools, now even, with very complex GUIs. Since everything is based on dotNET, we can utilise IronPython and some of the IDEs available for super quick GUI development. I used <a href="http://www.icsharpcode.net/OpenSource/SD/">SharpDevelop</a>, an open source IDE for writing dotNET applications, for all my GUI and code stuff. Then I just hook up MAXScript commands that I pass Python values to in order to perform some actions in 3ds Max, like opening a file from our server stored in Tactic. Or, create objects and list them in a ListView. Or even write a direct 3ds Max &#8211; Maya translator! Why not? <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Anyways, here are the methods and their purpose in 3ds Max:</p>
<ul>
<li>Python.run( &#60;string&#62; ) &#8212; will execute a Python script wrapped in double quotes (effectively a string).</li>
</ul>
<p>Example:</p>
<pre>
Python.run
(
	"import sys
	mxsCon.setResult( sys.version )"
)
</pre>
<p></br><br />
In this case, Python.run() will return whatever the mxsCon.setResult() will pass to it (more on that later).</p>
<ul>
<li>Python.runFromFile( &#60;string&#62; ) [ args:#() ] &#8212; will execute a Python script stored in an external file and alternatively pass it custom arguments.</li>
</ul>
<p>Example:</p>
<pre>
Python.runFromFile @"C:\myPythonScript.py" args:#( 10., true, #(1,2,3), "some string" )
</pre>
<p></br><br />
In Python, you&#8217;ll have to catch the passed arguments in order to use them, however the conversion of the data types will be done automatically for you.</p>
<ul>
<li>Python.inspect( &#60;data type&#62; ) &#8212; this method will inspect what data type you passed to it and how it will convert it to Python.</li>
<li>Python.getError() &#8212; this method returns the last unhandled exception in Python code.</li>
<li>Python.setVerbosity( &#60;int&#62; ) &#8212; allows you to set the level of verbosity for error reporting.</li>
<li>Python.getVerbosity() &#8212; retreives the level of verbosity you currently use.</li>
<li>Python.resetPy() &#8212; a very useful method for resetting our bridge residing in memory in case you&#8217;ve changed something radical in the source code etc&#8230;</li>
</ul>
<p>And here are the custom methods developed in C# for IronPython use in the scripts. These only exist when run via our Pythoner.dll module. If you run the Python scripts without Pythoner, you&#8217;ll have to handle their lack of presence. I&#8217;ve done this via a custom class that I import in the scripts I use. This is extremely flexible since when I run the code outside of 3ds Max, I can still use its functionality without having to deal with error handlers all over the place.</p>
<ul>
<li>mxsCon.setResult( &#60;data&#62; ) # this method will return whatever it encapsulates directly to 3ds Max as well as in Python should you need to work with it later in the script.</li>
</ul>
<p>Example:</p>
<pre>
import math

def myFunc( arg ):
	sum = arg + 100.
	return mxsCon.setResult( [arg, sum] )

if __name__ == '&#60;module&#62;':
	myFunc( math.pi )
</pre>
<p></br><br />
The myFunc function will not only return a List of whatever you pass to it as well as the result of addition, but it&#8217;ll also pass this List directly to MAXScript for later use in 3ds Max.</p>
<ul>
<li>mxsCon.getResult() # this method will only return the last value stored in memory using the .setResult() method. Useful for later usage in Python.</li>
<li>mxsCon.convert( &#60;data&#62; ) # this method will convert the input data types from Python to MAXScript compatible data types, but will return then wrapped as a string. This<br />
may be useful for other usage reasons. I used it for debugging or printing values in Python in MAXScript format.</li>
<li>mxsCon.execute( &#60;data&#62; ) # here&#8217;s where the magic happens. This method is quite complex. It not only evaluates whatever is passed to it in a String format, but it&#8217;ll also wait for the result from MAXScript and return it within Python. Another, very cool, feature of this method is similar to String formatting capabilities known from Python.</li>
</ul>
<p>Some examples of the mxsCon.execute() method:</p>
<pre>
# assume here's a ton of complex Python code that invokes this method
returnedVal = mxsCon.execute( r'Box()' )
# will create a box in 3ds Max and return OK (converted to True) back to Python.

returnedVal = mxsCon.execute( r'getDir {0}', r'#scripts' )</pre>
<p>The .execute method will first evaluate its input into a single string,<br />
in this case: r&#8217;getDir #scripts&#8217;, in a similar fashion the .format method works in Python.<br />
Then it&#8217;ll execute the command in MAXScript and retun its output back to Python.<br />
The output, in this case, will be a string: &#8216;C:\Program Files\Autodesk\3ds Max 2009\scripts&#8217;</p>
<p><a href="http://blog.duber.cz/wp-content/gallery/vids/pythoner_demo/pythoner_demo.html"><img src="http://blog.duber.cz/wp-content/uploads/pythoner_sharpdevelop_demo.png" alt="duberPython Features Demo" title="duberPython Features Demo" width="560" height="350" class="aligncenter size-full wp-image-468" /></a></p>
<p>But, enought with the talk, see it for yourself in action in this short Windows.Forms demo. (clicking the image will take you to the video)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/duberpython-features-demonstration/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>duberPython is coming to life!</title>
		<link>http://blog.duber.cz/3ds-max/duberpython-is-coming-to-life</link>
		<comments>http://blog.duber.cz/3ds-max/duberpython-is-coming-to-life#comments</comments>
		<pubDate>Thu, 10 Dec 2009 23:59:03 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[alpha]]></category>
		<category><![CDATA[bridge]]></category>
		<category><![CDATA[communication]]></category>
		<category><![CDATA[conversion]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[duber]]></category>
		<category><![CDATA[duberpython]]></category>
		<category><![CDATA[independent]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[pythonier]]></category>
		<category><![CDATA[tunnel]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/3ds-max/duberpython-is-coming-to-life</guid>
		<description><![CDATA[
I am very excited to present a very early development results for our own Python implementation in 3ds Max.
First a bit of an intro. At duber, I&#8217;ve setup everything around Python, the most versatile and powerful language I&#8217;ve ever seen. I felt in love with Python so much that it even influenced my decision to [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://blog.duber.cz/wp-content/uploads/duberpython_banner.png' alt='duberPython banner' /></p>
<p>I am very excited to present a very early development results for our own Python implementation in 3ds Max.</p>
<p>First a bit of an intro. At duber, I&#8217;ve setup everything around <a href="http://www.python.org">Python</a>, the most versatile and powerful language I&#8217;ve ever seen. <a href="http://blog.duber.cz/3ds-max/im-loving-python">I felt in love with Python</a> so much that it even influenced my decision to leave <a href="http://eyeonline.com/Web/EyeonWeb/Products/fusion6/fusion6.aspx">Fusion</a> (my favourite compositing app) and dive into <a href="http://www.thefoundry.co.uk/pkg_overview.aspx?ui=CBC2593A-2C9F-4EF9-84BE-C198B0171453">Nuke</a> (my, now, most favourite compositing app). I even invested in a commercial data and asset management system, <a href="http://southpawtech.com/tactic.html">Tactic</a>, that is entirely written in Python. I run tons of custom Python scripts to tie together programs such as Tactic, Nuke, <a href="http://www.iridas.com/framecycler/">FrameCycler</a>, Photoshop etc&#8230; etc&#8230; But the last missing piece to the entire pipeline puzzle was 3ds Max.</p>
<p><span id="more-319"></span></p>
<p>There were initiatives to bring Python into Max, both from <a href="http://area.autodesk.com/blogs/chris/my_first_forays_into_net_and_ironpython_from_maxscript">Autodesk</a> and from <a href="http://forums.cgsociety.org/showthread.php?f=98&#038;t=816475">3rd party developers</a>. The problem is, none of those are final, open-source, nor fully functional.</p>
<p>What I need with Max, at least for now, is to be able to communicate with the Python tools running at my studio. I need Max to be able to communicate with Tactic. I need it to communicate with FrameCycler. And I need it to communicate with Nuke. Since I have most of the tiny scripts up and running that provide this communication layer, the last bit missing was Max being able to execute Python scripts and catch Python&#8217;s outputs.</p>
<p>We&#8217;ve achieved this with IronPython and a bit of C# magic.</p>
<p>Even though IronPython is different from CPython (the regular distro), it provides some additional functionality and mainly, it communicates flawlessly with dotNET. Another area that Max is well tied to. So this made for a perfect match! All we needed was a layer, a bridge of some sort, that&#8217;d make IronPython play nice with Max and vice versa. What we have right now is a very early Alpha build, very simple, elegant and light, that does just that! Maybe, if Autodesk doesn&#8217;t do it for us, we might extend this functionality beyond a simple communication layer and might actually make Python scripts command 3ds Max, so that we will be able to create objects, modify them, manipulate with the scene etc&#8230; etc&#8230; all directly via Python&#8217;s code. But for now, all I need is a two way communication tunnel that bridges the gap between MAXscript and Python. So far, we can run directly Python commands/scripts from within MAXScript code and we can run Python script files stored on the HDD and return results in MAXScript.</p>
<p>Here&#8217;s a sample of what we have right now:</p>
<p><img src='http://blog.duber.cz/wp-content/uploads/runpython.png' alt='Python scripts running directly from MXS' /></p>
<p><img src='http://blog.duber.cz/wp-content/uploads/runpython_str.png' alt='Python scripts running directly from MXS' /></p>
<p><img src='http://blog.duber.cz/wp-content/uploads/runpythonfile.png' alt='Python scripts running from a file inside of MXS' /></p>
<p>We&#8217;re working on proper data type wrapping right now. So far, we&#8217;ve got INTEGER, FLOAT and STRING types as well as DOUBLE type (naturally) being properly translated between MAXScript and Python. Hopefully I&#8217;ll have all the various data types being correctly translated to and from MAXScript and Python by the end of the week.</p>
<p>Also, the beauty of it is that it&#8217;s based on dotNET code and it was compiled independent on CPU architecture, which means it runs as fast and fine on both x86 machines and versions of Max as on x64 platforms. The other huge benefit is it is independent of 3ds Max entirely. It only requires dotNET Framework 3.5+ and IronPython libraries, but doesn&#8217;t require a recompile if I need it running under Max 9, 2008, 2009, 2010 or any other future versions of Max!</p>
<p>It is obviously not as robust or complex as <a href="http://forums.cgsociety.org/showthread.php?f=98&#038;t=816475">Blur&#8217;s latest Python plugin</a>, but thanks to that, it&#8217;s very versatile and flexible, which is great! <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/duberpython-is-coming-to-life/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Python in 3ds Max &#8211; FINALLY POSSIBLE!</title>
		<link>http://blog.duber.cz/3ds-max/python-in-3ds-max-finally-possible</link>
		<comments>http://blog.duber.cz/3ds-max/python-in-3ds-max-finally-possible#comments</comments>
		<pubDate>Sun, 25 Oct 2009 20:14:30 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[opinions]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[access]]></category>
		<category><![CDATA[accessible]]></category>
		<category><![CDATA[blur]]></category>
		<category><![CDATA[blurpython]]></category>
		<category><![CDATA[embedded]]></category>
		<category><![CDATA[exec]]></category>
		<category><![CDATA[execute]]></category>
		<category><![CDATA[from]]></category>
		<category><![CDATA[in]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[Max]]></category>
		<category><![CDATA[PyQt]]></category>
		<category><![CDATA[Qt]]></category>
		<category><![CDATA[run]]></category>
		<category><![CDATA[tactic]]></category>
		<category><![CDATA[trolltech]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/3ds-max/python-in-3ds-max-finally-possible</guid>
		<description><![CDATA[
Yes! Once again, Blur studio showed how it&#8217;s supposed to be done.
They&#8217;ve released, or allowed their Eric Hulser to release, an updated version of their blurPython modules for 32bit and 64bit 3ds Max versions from Max 9 all the way up to 2009! And not only that. They&#8217;ve also provided libs and modules for tying [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://blog.duber.cz/wp-content/uploads/blurpython_banner.png' alt='blurPython Banner' /></p>
<p>Yes! Once again, <a href="http://www.blur.com">Blur studio</a> showed how it&#8217;s supposed to be done.</p>
<p>They&#8217;ve released, or allowed their Eric Hulser to release, an updated version of their <a href="http://forums.cgsociety.org/showthread.php?f=98&#038;t=816475">blurPython modules for 32bit and 64bit 3ds Max</a> versions from Max 9 all the way up to 2009! And not only that. They&#8217;ve also provided libs and modules for tying up Python, 3ds Max and Qt together! This is massive news as I&#8217;ve been trying to get Python (concretely IronPython) work in 3ds Max but I&#8217;ve been constantly hitting road blocks until I finally bumped into Blur&#8217;s updated blurPython.</p>
<p><span id="more-286"></span></p>
<p>The problem with IronPython would be the .NET classes that are required in order to embed IronPython inside 3ds Max. Since I don&#8217;t know C# at all, I&#8217;m not able to write custom wrappers to use in this combination, unfortunately. Another issue would be incompatibility with other programs that already run Python natively, such as Nuke or Maya, that I want to tie together under one managed pipeline environment in my studio. IronPython is a Microsoft opensource project that brings Python programming to .NET or vice-versa, which is great on many levels and I was really excited on bringing this to Max, since Max is already pretty tied in with .NET and I thought this might have been the best and easiest solution.</p>
<p>Well, nevermind, I&#8217;ll leave that part on Autodesk, if they ever decide to bring Python to Max. But for now, I&#8217;ll be happily enjoying Blur&#8217;s blurPython effort with Qt, which I was about to learn anyways (I bought a <a href="http://www.amazon.com/Programming-Python-Prentice-Software-Development/dp/0132354187/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1256498711&#038;sr=8-1">Rapid GUI Programming with Python and Qt</a> book a while back, but haven&#8217;t gotten to reading it yet).</p>
<p>After a few minutes fiddling with Python 2.6, Qt and a bunch of modules required in order to make blurPython run under Max, I&#8217;ve finally managed to get Python code executed and working correctly in Max!</p>
<p><a href='http://blog.duber.cz/wp-content/uploads/blurpython_max.png' title='blurPython running in Max internally' rel="lightbox[286]"><img src='http://blog.duber.cz/wp-content/uploads/blurpython_max.thumbnail.png' alt='blurPython running in Max internally' /></a></p>
<p>And with a bit of help from <a href="http://www.mackevision.de/index.html">Thorsten Kaufmann</a>, I also managed to get Python code up and running from an external editor, which is very useful! Although I use SciTe, which got implemented as a MAXScript Pro Editor in Max 2008, I believe, I can&#8217;t get lexer and other language syntax up and running in it since it&#8217;s heavily modified and fit for MAXScript only, which sucks. So I use SciTe externally for Python and simply run the code from there to show up in Max.</p>
<p><a href='http://blog.duber.cz/wp-content/uploads/blurpython_external.png' title='blurPython running in Max from external editor' rel="lightbox[286]"><img src='http://blog.duber.cz/wp-content/uploads/blurpython_external.thumbnail.png' alt='blurPython running in Max from external editor' /></a></p>
<p>The only drawback of this is the fact that we&#8217;ll be 100% dependant on Blur for maintainig these plugins and modules. Well, modules won&#8217;t be an issue, these are open-source, but the parts that are closed-source are inaccessible to other programmers. So, whatever Blur decides to do with their plugins, we&#8217;ll have to go their way. Which is a bit problematic for a studio to rely their entire 3ds Max pipline on this (like mine). But we&#8217;ll see, maybe Autodesk will acquire or at least somehow officially support Blur&#8217;s efforts. Maybe Blur will decide to release the package as an open-source project to the public, or perhaps as a commercial package? If not, we&#8217;ll still be dependant on on thing or another, but this might prove to be either a huge win or a huge loss situation. The pros are, thankfully, huge for me, at least. So I&#8217;ll take the risk and adopt blurPython in my pipeline, since I need it for accessing <a href="http://southpawtech.com/">Tactic</a> projects and SObjects from within Max.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/python-in-3ds-max-finally-possible/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Python 2.6 released</title>
		<link>http://blog.duber.cz/software/python-26-released</link>
		<comments>http://blog.duber.cz/software/python-26-released#comments</comments>
		<pubDate>Thu, 02 Oct 2008 19:14:37 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[2.6]]></category>
		<category><![CDATA[2_6]]></category>
		<category><![CDATA[download]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[full]]></category>
		<category><![CDATA[hot]]></category>
		<category><![CDATA[newest]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[released]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/software/python-26-released</guid>
		<description><![CDATA[
Python 2.6 had been officially released on 01.09.2008! Some really great new features but still compatible with 2.5 code, which is great for slowly transitioning to the upcoming Python 3000.
Don&#8217;t hesitate a second and go for the download!
]]></description>
			<content:encoded><![CDATA[<p><img src='http://blog.duber.cz/wp-content/uploads/python_26_banner.png' alt='Python 2.6 banner' /></p>
<p>Python 2.6 had been officially released on 01.09.2008! Some really great new features but still compatible with 2.5 code, which is great for slowly transitioning to the upcoming Python 3000.</p>
<p>Don&#8217;t hesitate a second and <a href="http://python.org/download/releases/2.6/">go for the download</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/software/python-26-released/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>dotNET sweetness for Maya</title>
		<link>http://blog.duber.cz/maya/dotnet-sweetness-for-maya</link>
		<comments>http://blog.duber.cz/maya/dotnet-sweetness-for-maya#comments</comments>
		<pubDate>Thu, 11 Sep 2008 12:05:37 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[develop]]></category>
		<category><![CDATA[dotNET]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[GUI]]></category>
		<category><![CDATA[IronPython]]></category>
		<category><![CDATA[PythonNet]]></category>
		<category><![CDATA[run]]></category>
		<category><![CDATA[under]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/maya/dotnet-sweetness-for-maya</guid>
		<description><![CDATA[
When I first started developing some tools, to speed up and aid our pipeline, in Maya I was furious to find out about Maya&#8217;s implemented GUI tools and methods. It was extremely unintuitive, very badly documented (especially regarding examples of the given object etc&#8230;) and heavily limiting. What I&#8217;d love to have in Maya was [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://blog.duber.cz/wp-content/uploads/maya_dotnet_banner.png' alt='maya_dotnet_banner' /></p>
<p>When I first started developing some tools, to speed up and aid our pipeline, in Maya I was furious to find out about Maya&#8217;s implemented GUI tools and methods. It was extremely unintuitive, very badly documented (especially regarding examples of the given object etc&#8230;) and heavily limiting. What I&#8217;d love to have in Maya was something similar to Max&#8217;s GUI objects I was used to.</p>
<p><span id="more-93"></span></p>
<p>Especially ever since Max 9, where we finally gained access to the beautiful dotNET framework and its objects, classes etc. I was looking for a similar solution. The only problem with dotNET is its platform dependence. As it&#8217;s a Microsoft framework it, obviously, only works on Windows. I&#8217;ve heard about Mono for Linux, but since I don&#8217;t work on Linux and have very limited knowledge of it, I didn&#8217;t investigate any further. There are some other options for platform-independent GUI development, like <a href="http://trolltech.com/products/qt/">Qt</a>, which I&#8217;m yet to go through. It&#8217;s definitely worth looking into, but the great advantage of dotNET, on the other hand, is its presence on virtually any Windows machine, which is simply awesome for heavy tools deployment across multiple machines in a studio environment (I can&#8217;t imagine making all our artists to install Qt). So, the obvious step was to look for a way to get dotNET run under Maya.</p>
<p>After searching the net, I quickly realized it won&#8217;t be such a simple task as with many other tools I&#8217;ve ported to Maya in the form of modules for Python. There is IronPython, which runs under its own interpreter, which makes it impossible to implement in Maya (very sad!), but then I bumped into a project, which seems to be lacking a bit of active development, but looked promising: <a href="http://pythonnet.sourceforge.net/">PythonNet</a>.</p>
<p>There&#8217;s a little bit of a glitch. There&#8217;s no x64 port and, what&#8217;s more irritating, the release version I managed to run under Maya only supports dotNET 1.1, which is a real pitty as the tools you&#8217;ll be able to create will have slightly limited functionality for more advanced tools development, but nothing that&#8217;d cripple the actual usefulness and richness of the platform, only some more advanced and newly added classes or methods won&#8217;t be supported.</p>
<p>An example of the dotNET&#8217;s listView object used under Maya:<br />
<img src='http://blog.duber.cz/wp-content/uploads/dotnet_lv_maya.png' alt='dotNET_listView_in_maya'/></p>
<p>So, all you need is to download the <a href="http://sourceforge.net/project/showfiles.php?group_id=162464&#038;package_id=183296">PythonNet 1.0 RC2 for dotNET 1.1</a> and install CLR.dll and Python.Runtime.dll in Maya&#8217;s bin folder. Done. From there on, you&#8217;ll be able to import a CLR module (note the upper-case) and access the dotNET objects and namespaces through it. There are also some nice examples of code to get you going.</p>
<p>Another dotNET example of an actual simple tool I developed for automatic Point Cache assignments:<br />
<img src='http://blog.duber.cz/wp-content/uploads/pcs_agent_maya.png' alt='point_caches_agent' /></p>
<p>Here, again, Python really excells in these matters. I&#8217;m able to develop a fairly complex GUI for my tools and then instance, inherit and mainly overflow the operators of the GUI, so, in the end, I can plot the same GUI for many various functions, which is very useful.</p>
<p>Right now I&#8217;m looking into some ways of getting the alpha verision of PythonNet 2.0, which supports dotNET 2.0 objects, to run under Maya in both x86 and x64 modes. If I get it going, I&#8217;ll post the way as well as the compiled modules (as I feel it&#8217;ll be necessary).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/maya/dotnet-sweetness-for-maya/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Checksums in 3ds Max</title>
		<link>http://blog.duber.cz/3ds-max/checksums-in-3ds-max</link>
		<comments>http://blog.duber.cz/3ds-max/checksums-in-3ds-max#comments</comments>
		<pubDate>Sun, 10 Aug 2008 20:19:54 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[3ds]]></category>
		<category><![CDATA[checksum]]></category>
		<category><![CDATA[checksums]]></category>
		<category><![CDATA[class]]></category>
		<category><![CDATA[classes]]></category>
		<category><![CDATA[dotNET]]></category>
		<category><![CDATA[integration]]></category>
		<category><![CDATA[Max]]></category>
		<category><![CDATA[MD5]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/3ds-max/checksums-in-3ds-max</guid>
		<description><![CDATA[After reading a very interesting and helpful article about checksums and how practical they are for comparing large datasets over at Adam Pletcher&#8217;s Tech Art Tiki blog, I was immediately interested in such methods as I&#8217;m doing some R&#38;D on data management in a larger creative environment and need such a feature. Unfortunately, MAXScript natively [...]]]></description>
			<content:encoded><![CDATA[<p>After reading a very interesting and helpful article about checksums and how practical they are for comparing large datasets over at <a href="http://techarttiki.blogspot.com/2008/03/checksums.html">Adam Pletcher&#8217;s Tech Art Tiki blog</a>, I was immediately interested in such methods as I&#8217;m doing some R&amp;D on data management in a larger creative environment and need such a feature. Unfortunately, MAXScript natively doesn&#8217;t support MD5 hashes (or any other kinds of hashes), so you&#8217;re pretty much stuck with just a few options.</p>
<p><span id="more-86"></span></p>
<p>One of them is, <a href="http://techarttiki.blogspot.com/2008/03/calling-python-from-maxscript.html">as Adam describes</a>, utilizing Python from within Max and call its native MD5 functions. There are two ways, but both are very limiting. One of them is registering a COM server from within Python and calling the functions through OLE objects from Max. The other possibility is using blur&#8217;s implementation of Python&#8217;s interpreter, blurPython, and calling the module, somehow, natively. Both of these methods work and are quite easy to setup, however, both of them are very hard to be deployed in a more complex environment.</p>
<p>What I need is an integrated MAXScript solution that yields the same result as the MD5 implementation in Python, so that I&#8217;ll be able to directly compare results from within Maya and Max for example. After searching the web and looking into the MD5 algorithm I quickly realized that re-writing the algorithm myself in MAXScript isn&#8217;t the way. But thankfully, Microsoft implemented a vast number of hash algorithms into its .NET framework as I learned on the web, so this looked like the obvious choice.</p>
<p>After a few minutes at the <a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.aspx">MSDN central</a> I found what I&#8217;d been looking for. An actual MD5 implementation. However, as .NET is quite a comprehensive and large framework, the implementation isn&#8217;t as straight forward as the one found in Python. Nevertheless, all you need are two classes:</p>
<p><code>"System.Security.Cryptography.MD5"<br />
"System.Text.Encoding"</code></p>
<p>These are the .NET strings you&#8217;ll need for instancing the classes in MAXScript. So, let&#8217;s take a look at the code block:</p>
<p><code><br />
md5Class = dotNetClass "System.Security.Cryptography.MD5"<br />
encoding = dotNetClass "System.Text.Encoding"<br />
MD5 = md5Class.Create()<br />
</code></p>
<p>In this block, I&#8217;ve declared three variables, the first two were instances of the .NET classes and the last one, <em>MD5</em>, is a newly created object from the Cryptograpy.MD5 class called by the .NET .Create() method. You have a few options for the method to specify how the MD5 algorithm should treat your input, but I left it at default as I don&#8217;t need anything specific.</p>
<p>Now we are set to go through the last step, which is providing the MD5 object with arguments for computing the hash. This is done through another .NET method called .ComputeHash(). Unfortunately for us, the ComputeHash method only accepts either a Byte[] array or a Stream object (not sure whether it&#8217;d take a Max&#8217;s fileStream object directly, but mu guess is it wouldn&#8217;t) to generate the hash based on the input data. This is where the System.Text.Encoding class comes in handy, because it has a method for converting a string through a concrete character table (ASCII, UTF-8, etc&#8230;) to bytes. I&#8217;ve chosen the UTF-8 even though I&#8217;m certain I&#8217;m not likely to use anything beyond the ASCII table definition. The procedure to get the byte code of your string is as follows:</p>
<p><code><br />
encoding = dotNetClass "System.Text.Encoding"<br />
encoding.UTF8.GetBytes(myString)</code></p>
<p>Bear in mind that you can use different character tables to facilitate your concrete needs, but basically this is all you need to pass the MD5 function to calculate your checksum. With this knowledge, the following code is all there is to calculating correct MD5 checksums inside 3ds Max:</p>
<p><code>md5Class = dotNetClass "System.Security.Cryptography.MD5"<br />
encoding = dotNetClass "System.Text.Encoding"<br />
MD5 = md5Class.Create()<br />
hashArr = MD5.ComputeHash(encoding.UTF8.GetBytes(myString)) -- it's smarter to store the resulting array of byte values for later manipulation<br />
</code></p>
<p>The interesting part is that by default, this method returns an array of decimal numbers:</p>
<p><code>#(13, 87, 80, 212, 152, 226, 236, 248, 58, 163, 91, 29, 33, 199, 60, 102)</code></p>
<p>I don&#8217;t know of any .NET method or a property that&#8217;d return a standard hexadecimal value as we&#8217;re used to from, for example, Python. However, it is easy to overcome with a formatting function (since Max 2008 or with an AVG extension in previous versions) called <em>formattedPrint</em>. I wrote a custom function that solves this whole issue and does exactly what you&#8217;d expect from a natively implemented function, it simply expects a value and returns a hexadecimal (correctly formatted) string. Make sure you check the documentation for the correct <em>formattedString</em> arguments as they are quite important in this case for correct formatting of the hexadecimal values! Here&#8217;s the code:</p>
<p><code>fn MD5Checksum input =<br />
(<br />
&nbsp;&nbsp;&nbsp;&nbsp;md5Class = dotNetClass "System.Security.Cryptography.MD5"<br />
&nbsp;&nbsp;&nbsp;&nbsp;encoding = dotNetClass "System.Text.Encoding"<br />
&nbsp;&nbsp;&nbsp;&nbsp;myHash = "" as string<br />
&nbsp;&nbsp;&nbsp;&nbsp;myString = "" as string<br />
&nbsp;&nbsp;&nbsp;&nbsp;try (myString = input as string) catch (return false)<br />
&nbsp;&nbsp;&nbsp;&nbsp;MD5 = md5Class.Create()<br />
&nbsp;&nbsp;&nbsp;&nbsp;hashArr = MD5.ComputeHash(encoding.UTF8.GetBytes(myString))<br />
&nbsp;&nbsp;&nbsp;&nbsp;for o in hashArr do<br />
&nbsp;&nbsp;&nbsp;&nbsp;(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myHash += formattedPrint o format:"02x"<br />
&nbsp;&nbsp;&nbsp;&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;return myHash<br />
)</code></p>
<p>To sum this up, let&#8217;s compare this custom MD5 function based on .NET classes with Python&#8217;s native implementation. For the sake of completeness, here&#8217;s the code you&#8217;ll need in order to generate an MD5 hash in Python (I&#8217;ll use the same name &#8220;myString&#8221; for the string variable as in the MXS example above for clarity):</p>
<p><code>import hashlib<br />
hashlib.md5(myString).hexdigest()</code></p>
<p>Yeah, I know, very simple, isn&#8217;t it <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> Yet again, <a href="http://blog.duber.cz/3ds-max/im-loving-python">Python kicks some serious ass</a> here! Anyways, let&#8217;s test it on a long string (just to make sure both of the methods yield the same result) like:</p>
<p><code>"ThisIsAVeryLongStringThatIsHardToReadButShouldStressTestBothMethodsEnough"</code></p>
<p>Both MAXScript and Python return (strings):</p>
<p><code>"0d5750d498e2ecf83aa35b1d21c73c66"</code></p>
<p>So, this is it, now you should be more familiar with .NET classes, how they work from within MAXScript and that the whole .NET framework is one hell of a good job by Microsoft for developers of any kind, such as TDs working in DCC applications, which is sweet! <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/checksums-in-3ds-max/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Connecting to a MySQL database from CG applications.</title>
		<link>http://blog.duber.cz/3ds-max/connecting-to-a-mysql-database-from-cg-applications</link>
		<comments>http://blog.duber.cz/3ds-max/connecting-to-a-mysql-database-from-cg-applications#comments</comments>
		<pubDate>Sat, 09 Aug 2008 22:19:19 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[3d]]></category>
		<category><![CDATA[3ds]]></category>
		<category><![CDATA[accessing]]></category>
		<category><![CDATA[assembly]]></category>
		<category><![CDATA[connecting]]></category>
		<category><![CDATA[connection]]></category>
		<category><![CDATA[connector]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[dotNET]]></category>
		<category><![CDATA[Max]]></category>
		<category><![CDATA[ODBC]]></category>
		<category><![CDATA[string]]></category>
		<category><![CDATA[using]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/3ds-max/connecting-to-a-mysql-database-from-cg-applications</guid>
		<description><![CDATA[I&#8217;ve been recently doing some R&#38;D on MySQL databases and connection through Python in Maya as well as Python in Max (through blurPython library), but I couldn&#8217;t seem to have found a way to connect to a MySQL database via ODBC. The problem lied in OLE methods as they&#8217;re not both much documented in MAXScript [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been recently doing some R&amp;D on MySQL databases and connection through Python in Maya as well as Python in Max (through blurPython library), but I couldn&#8217;t seem to have found a way to connect to a MySQL database via ODBC. The problem lied in OLE methods as they&#8217;re not both much documented in MAXScript reference and they&#8217;re tied to the operating system, not Max directly. But thankfully, I bumped into a solution today, out of a blue <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><span id="more-54"></span></p>
<p>To save you some time, don&#8217;t bother trying to connect to the database (db for short) via the standard example:<br />
<code>DogConn=createOLEObject "ADODB.Connection"<br />
DogConn.Open "driver={SQL Server}; server=localhost; database=test"</code></p>
<p>output:<br />
<code><OLEObject:ADODB.connection><br />
-- Runtime error: OLEObject method call failed:<br />
Error Message 1: [Microsoft][ODBC SQL Server Driver][DBNETLIB]SQL Server does not exist or access denied.<br />
method: open()</code></p>
<p>This concrete driver is a Microsoft SQL Server driver, so obviously, this doesn&#8217;t make much senese to use this method for connecting to a MySQL database. Since there are numerous ways of setting up the connection via different providers or drivers I was lost. But thankfully , Sun provides its own <a href="http://dev.mysql.com/downloads/connector/odbc/5.1.html">ODBC connectors</a> for various operating systems, including 64bit versions for Windows. So download the one that fits your OS and after installing it, just check what name the driver has assigned in the Data Sources(ODBC) under Administrative Tools. It should read &#8220;MySQL ODBC 5.1 Driver&#8221;, which is exactly what you need for successful connecting to a MySQL database. Easily enough, from the comprehensive list of example connection strings found at <a href="http://www.connectionstrings.com/?carrier=mysql">ConnectionStrings.com</a> I was finally able to write this code:</p>
<p><code>DogConn=createOLEObject "ADODB.Connection"<br />
DogConn.Open "Driver={MySQL ODBC 5.1 Driver};Server=serverName;Database=dbName;User=userName; Password=password"</code></p>
<p>Even though it returns &#8220;undefined&#8221;, don&#8217;t be alarmed, this is a good thing. So, now you&#8217;re good to go and start fully appretiating the whole database purpose and design!</p>
<p>As for dotNET. It&#8217;s much easier (as it&#8217;s Microsoft&#8217;s next &#8220;big thing&#8221;) to code for and also you&#8217;re less likely to bump into similar problems. Again, download <a href="http://dev.mysql.com/downloads/connector/net/5.2.html">the latest .NET connector from Sun</a> and try executing this snippet in Max 9+:</p>
<p><code>dotNet.loadAssembly "C:\\Program Files (x86)\\MySQL\\MySQL Connector Net 5.2.2\\Binaries\\.NET 2.0\\MySql.Data.dll"<br />
DBConnection = dotNetObject "MySql.Data.MySqlClient.MySqlConnection"<br />
DBConnection.ConnectionString = "Server=192.168.1.14;Database=test;Uid=root;Pwd=root"<br />
DBConnection.open()</code></p>
<p>dotNET works in a slightly different way. Instead of loading up a provider or service, it loads up an &#8220;assembly&#8221;, which is a dll, in this case Sun&#8217;s .NET connector, and then allows you to work with its methods. So I first loaded the dll up, then fired the dotNetObject function, then I specified the connection string and finally opened up the connection. Then you&#8217;re good to go!</p>
<p>Even simplier is the Python way of things, as usual <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> All you need is a <a href="http://sourceforge.net/projects/mysql-python">MySQLdb module available at SourceForge.net</a>, install it for your version of Python and then try running this code:</p>
<p><code>import MySQLdb as db<br />
conn = db.connect("serverName","userName","password","databaseName")</code></p>
<p>Now you&#8217;re ready for some serious querying! <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> It really is this simple and that&#8217;s why <a href="http://blog.duber.cz/3ds-max/im-loving-python">I&#8217;m really loving Python</a>. Anyways, these were just a few examples of how to connect to a MySQL database via ODBC, .NET and Python, which is really all you&#8217;ll ever need for connecting to MySQL from 3ds Max, Maya or XSI.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/connecting-to-a-mysql-database-from-cg-applications/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Scripting in Maya through Python? Get used to a lot of string operations.</title>
		<link>http://blog.duber.cz/3ds-max/you-want-to-script-in-maya</link>
		<comments>http://blog.duber.cz/3ds-max/you-want-to-script-in-maya#comments</comments>
		<pubDate>Wed, 14 May 2008 22:48:16 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[3ds]]></category>
		<category><![CDATA[compare]]></category>
		<category><![CDATA[comparing]]></category>
		<category><![CDATA[comparison]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[loop]]></category>
		<category><![CDATA[Max]]></category>
		<category><![CDATA[operations]]></category>
		<category><![CDATA[parsing]]></category>
		<category><![CDATA[replacing]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[string]]></category>
		<category><![CDATA[while]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/3ds-max/you-want-to-script-in-maya</guid>
		<description><![CDATA[
I find myself scripting in Maya more and more often. As I&#8217;ve expressed many times already, I really love and appretiate Python&#8217;s way of dealing with things, so having this language available in Maya is a blessing. The most beautiful part is when software actually does all the hard and annoying work for you  [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://blog.duber.cz/wp-content/uploads/maya_hypergraph_screenshot.png' alt='Maya hypergraph banner' /></p>
<p>I find myself scripting in Maya more and more often. As I&#8217;ve expressed many times already, I really love and appretiate Python&#8217;s way of dealing with things, so having this language available in Maya is a blessing. The most beautiful part is when software actually does all the hard and annoying work for you <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> Scripting in Maya using Python hadn&#8217;t been designed the way it should be. Unfortunately, Python only serves as a &#8220;wrapper&#8221; around MEL commands and MEL architecture. Fortunately there are attempts at simplifying Python scripting in Maya, such as PyMEL from <a href="http://www.luma-pictures.com/ncomPublish/index.html">Luma Pictures</a> (which is a studio I feel honored to cooperate with on <a href="http://www.imdb.com/title/tt1041804/">The Nutcracker: The Untold Story</a>), which is a fantastic &#8220;plug-in&#8221; for any Maya TD! which was, not surprisingly, done solely through Python itself <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> A fantastic demonstration of Python&#8217;s power. However, PyMEL isn&#8217;t the topic for this short post, maybe later, when I get more familiar with it and gain more experience using it.</p>
<p><span id="more-55"></span></p>
<p>The main reason for getting used to working and parsing a lot of string data is, as stated above, because, by default, Python acts as sort of a &#8220;wrapper&#8221; around Maya&#8217;s native MEL language. You&#8217;ll be passing tons of string arguments and parameters to Maya&#8217;s Python interpreter, so knowing how to deal with long strings is a must. Today I was solving a trivial issue of assigning numerous texture inputs to quite a few <em>tripleShadingSwitch</em> objects for some complex material and shader definition. The whole, manual, procedure would have been very straight forward, but extremely tedious and time consuming. So, as a TD, I was asked to write a little script that&#8217;d do the trick with a very limited user input, which basically meant no UI, which is a good thing for a scripter. If you&#8217;ve done some UI coding, you know what I&#8217;m talking about, especially in connection to Maya <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>In the end, I dealt with a lot of string variables that were passed throughout the script in Python. It&#8217;d have been a pain in the ass doing this sort of thing in MAXScript, as MAXScript isn&#8217;t very &#8220;string friendly&#8221;. I mean, of course there are various string functions available, but they don&#8217;t come even close to waht Python has to offer!  A single Python module, called &#8220;string&#8221;, did all and much more I needed. For example, after importing the module, I was able to, very effectively, break a string down based on a keyword argument and separate individual words. While this concrete example is very easily doable in MAXScript, not so easily doable in MEL, there are many other examples that aren&#8217;t so easy to do in MAXScript or MEL in comparison to Python. One example for all. Let&#8217;s say you have to deal with namespaces. They usually occur in applications like Maya or MotionBuilder which preven users from naming individual objects the same name under the same level in a hierarchy. When you have multiple hierarchies, you may bump into objects with the same name. Maya will return the shortest namespace possible, so instead of returning a &#8220;Sphere1&#8243; it&#8217;ll return a &#8220;myHierarchy|secondLevel|thirdLeve|Sphere1&#8243; if multiple objects with this particular name exist in the scene. So, for whatever reason, what if you need to replace the specific namespace separator with something else? Here&#8217;s an example of a very long string of several words separated with a colon (as it&#8217;s a common character for identifyingnamespaces) that you want to replace by an underscore character, let&#8217;s say for compatibility reasons (say you want to pass this string to Max). Here&#8217;s how to do it in Python (including Python in Maya):</p>
<p><code>from string import *<br />
aVeryLongString = "a:very:very:very:very:long:string:with:namespaces"<br />
aNewString = replace(aVeryLongString,":","_")</code></p>
<p>the result: <em>a_very_very_very_very_long_string_with_namespaces</em></p>
<p>Great! Only three lines of code and very little brain usage was actually needed to perform this task <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> How about MAXscript? Well, MAXscript has a function called <em>replace()</em>, the problem is, it expects a string, a start position, a number of characters it should replace and an actual new string that&#8217;ll replace the old ones. Certainly usable, but very inconvenient, especially for casual or beginner scripters. How do you go about this limitation? You can&#8217;t import a &#8220;string&#8221; module or anything like that in MAXScript, so you have to write your own, custom, function to do that for you, which would be one of many ways to solve this little issue. For this example, I wrote a custom function that mimics Python&#8217;s <em>replace()</em> functino behavior including the number and nature of arguments it requires.</p>
<p><code>aVeryLongString = "a:very:very:very:very:long:string:with:namespaces"<br />
fn replaceAll str old kwrd =<br />
(<br />
&nbsp;&nbsp;&nbsp;&nbsp;while findString str old != undefined do<br />
&nbsp;&nbsp;&nbsp;&nbsp;(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str = replace str (findString str old) kwrd.count kwrd<br />
&nbsp;&nbsp;&nbsp;&nbsp;)<br />
&nbsp;&nbsp;&nbsp;&nbsp;return str<br />
)<br />
replaceAll aVeryLongString ":" "_"</code></p>
<p>the result: <em>a_very_very_very_very_long_string_with_namespaces</em></p>
<p>Basic break down: the function takes three arguments, the actual string you want to work with, and old character you want to replace (it supports more than one character) and a new, keyword (kwrd) to replace with. When invoked, it goes through a <em>while</em> loop to search for the <em>old</em> character string and replaces it with the new <em>kwrd</em> character string. After it&#8217;s all done it returns the new string.</p>
<p>Even though this took only a few more lines of code, I used two string specific functions and a loop clause all wrapped up in a custom function to do the trick for me. Besides, as I already mentioned, this method is much more complex and hard to code for an inexperienced scripter who just wants to perform a simple character replacement function. These are the tiny little differences that may cause a lot of trouble and headaches when developing really complex and large scripts or, for example, when you have a Junior TD at the studio who should help you out with simpler, smaller tasks and they bump into some similar problem like this one, which it&#8217;s as if they weren&#8217;t there since you end up doing the work yourself anyways.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/you-want-to-script-in-maya/feed</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>Serious technical limitations of proprietary languages.</title>
		<link>http://blog.duber.cz/3ds-max/serious-technical-limitations-of-proprietary-languages</link>
		<comments>http://blog.duber.cz/3ds-max/serious-technical-limitations-of-proprietary-languages#comments</comments>
		<pubDate>Tue, 13 May 2008 14:43:33 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[opinions]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[3ds]]></category>
		<category><![CDATA[ADODB]]></category>
		<category><![CDATA[Autodesk]]></category>
		<category><![CDATA[connection]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[Max]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[OLE]]></category>
		<category><![CDATA[open]]></category>
		<category><![CDATA[open-source]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[source]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/3ds-max/serious-technical-limitations-of-proprietary-languages</guid>
		<description><![CDATA[The more time you spend developing some more complex tools and code, the more you start appretiating all the open-source tools and add-ons you can get. Thankfully, Max and its MAXScript language is very widely used throughout the CG community, so, some times you don&#8217;t even have to start developing your own tools from scratch, [...]]]></description>
			<content:encoded><![CDATA[<p>The more time you spend developing some more complex tools and code, the more you start appretiating all the open-source tools and add-ons you can get. Thankfully, Max and its MAXScript language is very widely used throughout the CG community, so, some times you don&#8217;t even have to start developing your own tools from scratch, you can get either the whole package from sites like ScriptSpot or at least build your tools up on somebody else&#8217;s script. However, there are certain limitations that even a huge community, such as the one Max has, won&#8217;t be of much help.</p>
<p><span id="more-53"></span></p>
<p>I&#8217;ve been recently doing quite a lot of R&amp;D on XML, MySQL etc&#8230; in conjunction with Max and/or Maya and I constantly bump into obstacles when building the same code I did in Maya through Python, in MAXScript. The problem is, MAXScript is a proprietary language and therefore, you&#8217;re stuck with what you have. It&#8217;s a great, easy to learn and easy to master language, don&#8217;t get me wrong, but if you&#8217;re missing some specific features, you&#8217;re pretty much doomed. There are some extensions to be found on the net for MAXScript, but usually, they were done by a guy in similar situation you find yourself, but with extensive knowledge of Max&#8217;s SDK and C++/C# programming. I, unfortunately, have very limited knowledge of C++/C# programming and therefore I 100% rely on what I can find on the internet.</p>
<p>On the other hand, Python, for example, is an open-source scripting language. Very mature, very popular, ver widely accepted. This leads to a lot of individual, task specific, modules. So, in my case, recently, when I needed to write to or read from a XML file, I simply downloaded a <a href="http://pyxml.sourceforge.net/topics/">PyXML</a> package, read briefly the documentation, skimmed through some sample code and in a few hours I was able to write my own procedures to derive data from XML files and write them back to another XML. MAXscript doesn&#8217;t have any dedicated procedures/functions for such a task, so you either end up writing your own functions for this purpose, which is rather time consuming or you try your luck and try to search the internet for some already finished code, if there&#8217;s any. Same deal with the MySQL connection I was dealing with recently. Again, MAXScript doesn&#8217;t provide an extensive way of connecting to a database, it has an AODB object, which is quite limiting and a bit outdated nowdays. Thankfully, there seems to be a solution through dotNET objects, but I can&#8217;t use this method in Max prior to version 9 (you may not believe it, but I still prefer Max 8 nowdays <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ).</p>
<p>So, as you can see, languages such as Python are really a smart way to write your tools in and based your pipeline around. Obviously, Python isn&#8217;t the only scripting language of this kind, but it&#8217;s very popular and widely spread. I also highly recommend it because of its simple syntax, yet robust toolset. A very smart and far-sighted move from Guido van Rossum, kudos!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/serious-technical-limitations-of-proprietary-languages/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I&#8217;m loving Python!</title>
		<link>http://blog.duber.cz/3ds-max/im-loving-python</link>
		<comments>http://blog.duber.cz/3ds-max/im-loving-python#comments</comments>
		<pubDate>Sun, 02 Mar 2008 13:20:20 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[opinions]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[technical]]></category>
		<category><![CDATA[3ds]]></category>
		<category><![CDATA[Autodesk]]></category>
		<category><![CDATA[choose]]></category>
		<category><![CDATA[difference]]></category>
		<category><![CDATA[differences]]></category>
		<category><![CDATA[how]]></category>
		<category><![CDATA[language]]></category>
		<category><![CDATA[languages]]></category>
		<category><![CDATA[Max]]></category>
		<category><![CDATA[MEL]]></category>
		<category><![CDATA[MXS]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[which]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/opinions/im-loving-python</guid>
		<description><![CDATA[
Interestingly enough, when I started looking into extending my technical skills and knowledge beyond 3ds Max itself at first I got a bit frustrated. The reason was I thought (as probably many other technical artists out there, based on many discussions I read) that I spent years developing some scripting and technical skills to find [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://blog.duber.cz/wp-content/uploads/max_maya_python.png' alt='max_maya_python.png' /></p>
<p>Interestingly enough, when I started looking into extending my technical skills and knowledge beyond 3ds Max itself at first I got a bit frustrated. The reason was I thought (as probably many other technical artists out there, based on many discussions I read) that I spent years developing some scripting and technical skills to find out they were useless and I&#8217;ll have to learn something entirely different in order to stay at the cutting edge and still being competitive. Now while 3ds Max isn&#8217;t a factor here, it&#8217;s just a platform anyways, I dived into Maya recently and faced a, seemingly, difficult decision: do I go the MEL way or do I learn Python (available in Maya since 8.5)? The decision turned out to be petty simple! I&#8217;ll learn both! As I devoured the user reference files, some tutorials and some books, I found out that once you learn one scripting language syntax and logic, picking up any other (similar) language is quite easy.</p>
<p><span id="more-38"></span></p>
<p>Well, MEL, out of the three, comparatively, is the most difficult to grasp, not because of the sheer number of functions and attributes, but because the syntax is a bit too complicated (to my tastes) and the integration of MEL in Maya is also a little too restrictive (compared to MAXScript that I&#8217;m coming from). Now, the fact that Maya supports Python (too bad Max doesn&#8217;t natively support it as well), even though in a bit of a &#8220;MEL falvour&#8221; is pretty cool and only thanks to this fact I was able to pick up scripting in Maya very, very quickly! So, what&#8217;s so special about Python? Python is extremely easy to learn! Let me compare complexity-wise the three: Python < MAXScript < MEL and if I was to compare the three feature-wise: Python > MEL > MAXScript, so the clear winner is Python. Now, I&#8217;m primarily a 3ds Max TD, therefore I&#8217;m not able to fully appretiate Python&#8217;s power and strength from within Max, or am I? Thanks to the ever-so-awesome folks at <a href="http://www.blur.com">Blur</a> and their dedication to using 3ds Max in their pipeline, we have something that&#8217;s called &#8220;blurPython&#8221; which is an extension to MAXScript that allows you to call Python functions and modules. This alone takes scripting in Max to a whole new level! Even though you don&#8217;t have a direct Python syntax support in Max, you can&#8217;t call Max&#8217;s functions with Python (sort of, you can do that actually but it hasn&#8217;t got much to do with Python itself) you can access Python modules and functions from within Max, which is awesome. Now think about the feature set of Python, the fact that Python has been around for longer than Max itself and that it really is a production proven scripting framework and you&#8217;ve got a one hell of a powerful weapon in your TD arsenal! Especially if you&#8217;re into building custom pipelines and data sharing!</p>
<p>This article isn&#8217;t that much about all the posibilities you can do with Python itself, I&#8217;d rather like to compare some features of MEL, MXS (MAXScript) and PY (Python). So, first things first. When I started exploring Maya&#8217;s scripting and its logic, I buped several times into my old habbits of code testing, exploring and writing that I carried from Max. Some examples, when developing some code I tend to setup a bunch of testing global variables in order to speed up some UI testing, cut down on number of clicks in order to test out some tools with more complex UI etc&#8230; So I started developing some primitive scripts in Maya that were a bit ahead of <code>print "YAY!\n";</code> :D. Very soon I bumped in MEL&#8217;s design &#8220;limitation&#8221; (it&#8217;s not a limitation so to speak, only in my eyes it looks like a limitation, while in fact it&#8217;s simply a matter of design), I cannot reassign a different value class to an already declared variable. Let me explain: MXS allows me to do the following: <code>global testVar = "Hello!"; testVar = 10</code> which means: globally declare a variable called &#8220;testVar&#8221; and assign it a string value of &#8220;Hello!&#8221; then try to assign it an integer value of &#8220;10&#8243;. MEL won&#8217;t let you do this, which was to me, as a starting MEL scripter, quite confusing. The problem got more serious and I got frustrated even more when I learned that there was no way of &#8220;undeclaring&#8221; variables in MEL, so the &#8220;testVar&#8221; was available all the time during the session (which means until I restarted Maya). So, as recommended, you should always test your code in a local scope in MEL, which means writing your code within two curly braces: &#123; &lang;your code&rang; &#125;</p>
<p>This was quite shocking to me as a MXS scripter that I didn&#8217;t have the freedom to reassign variables with different value classes. Further on, the limitation touched all the aspects of the language I was used to, like arrays that can only carry a predefined value class, you can&#8217;t mix up integers with strings for example in MEL&#8217;s arrays (lists). So I put up with the fact and tried to learn a &#8220;different&#8221; syntax. I spent about 2 weeks learning MEL intentionally avoiding Python in Maya as, at first, I thought it was some kind of a &#8220;second layer&#8221; language above MEL that won&#8217;t do much difference in Maya. Oh, how wrong I was! Python, in fact, is much more powerful (to my surprise) in Maya than MEL. You can do the same with Python in Maya as you can with MEL, however, you can do much more with Python than you can do with MEL! This is quite interesting and since before MEL I had been looking into Python a bit, I got interested in it even more.</p>
<p>Everybody on the net says how easy, yet powerful, Python really is, I had to prove it to myself and started looking into the syntax and general Python logic. How glad and happy was I when I discovered that you CAN reassign different class values to a single variable (just like in MXS), I can mix up array (list) item classes any way I like (same as MXS), but the real surprise came when I realized that the PY syntax indeed was easy, so easy that I even think that it&#8217;s easier than MXS! And MXS really is easy to pick up and code in, believe me.</p>
<p>Ok, let&#8217;s take a look at some examples that I discovered which are very important in scripting in general. The globally declared variables in PY and MXS can be reassigned with a different value class! MEL doesn&#8217;t support this feature.</p>
<p>Python:<br />
<code>varA, varB, varC = 10, 20, 30<br />
print varA, varB, varC<br />
varA, varB, varC = "It", "just", "works"<br />
print varA, varB, varC</code></p>
<p>MAXScript:<br />
<code>varA = 10; varB = 20; varC = 30<br />
print varA; print varB; print varC<br />
varA = "It"; varB = "just"; varC = "works"<br />
print varA; print varB; print varC</code><br />
(notice the difference, Python actually supports multiple variable assignments on a single line in order as opposed to MXS)</p>
<p>MEL:<br />
<code>&#123;<br />
&nbsp;&nbsp;&nbsp;$varA = 10&#59; $varB = 20&#59; $varC = 30&#59;<br />
&nbsp;&nbsp;&nbsp;print ($varA+"\n"); print ($varB+"\n"); print ($varC+"\n")&#59;<br />
&nbsp;&nbsp;&nbsp;$varA = "It"; $varB = "just"; $varC = "works"&#59;<br />
&nbsp;&nbsp;&nbsp;print ($varA+"\n"); print ($varB+"\n"); print ($varC+"\n")&#59;<br />
&#125;</code><br />
Notice that MEL won&#8217;t let you reassign a different value class to an already created variable! It&#8217;ll try to convert the new class input to the one implicitly created. So, the code above will actually result in:</p>
<blockquote><p>// Warning: $varA = &#8220;It&#8221;; $varB = &#8220;just&#8221;; $varC = &#8220;works&#8221;; //<br />
// Warning: Converting string &#8220;It&#8221; to an int value of 0. //<br />
// Warning: $varA = &#8220;It&#8221;; $varB = &#8220;just&#8221;; $varC = &#8220;works&#8221;; //<br />
// Warning: Converting string &#8220;just&#8221; to an int value of 0. //<br />
// Warning: $varA = &#8220;It&#8221;; $varB = &#8220;just&#8221;; $varC = &#8220;works&#8221;; //<br />
// Warning: Converting string &#8220;works&#8221; to an int value of 0. //<br />
// Result: 0 //</p></blockquote>
<p>Now, let&#8217;s take a look at loops. These are most common in any scripter&#8217;s arsenal so you really have to learn how to write these in order to process repetitive tasks!</p>
<p>Python:<br />
<code>for i in range(1, 10, 2):<br />
&nbsp;&nbsp;&nbsp;print i</code></p>
<p>MAXscript:<br />
<code>for i = 1 to 10 by 2 do(print i)</code></p>
<p>MEL:<br />
<code>&#123;<br />
&nbsp;&nbsp;&nbsp;for ($i = 1; $i < 10; $i+=2)<br />
&nbsp;&nbsp;&nbsp;&#123;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print ($i+"\n");<br />
&nbsp;&nbsp;&nbsp;&#125;<br />
&#125;<br />
</code><br />
(notice that I put the MEL code in a local scope)</p>
<p>The MAXScript syntax in this case is far easier to read than Python and especially then MEL (also notice how many extra characters you have to put in the code in order to achieve the same result)</p>
<p>Another very useful feature is functions (in MEL they're called procedures). I'm yet into learning what all is possible with functions in Python, but what I've learnt so far is quite enough for my needs.</p>
<p>Python:<br />
<code>def sumTheNumbers(num1, num2):<br />
&nbsp;&nbsp;&nbsp;return num1+num2<br />
sumTheNumbers(10, 20) #call the function with some input numbers of choice<br />
sumTheNumbers("You ", "can!") #notice that Python doesn't actually care what class of variables you throw at it as long as it can perform the required task</code></p>
<p>MAXScript:<br />
<code>fn sumTheNumbers num1 num2 =<br />
&nbsp;&nbsp;&nbsp;(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return num1+num2<br />
&nbsp;&nbsp;&nbsp;)<br />
sumTheNumbers 10 20 -- call the function with some input numbers of choice<br />
sumTheNumbers "You " "can!" -- notice that MAXScript doesn't actually care what class of variables you throw at it as long as it can perform the required task</code><br />
(same thing, MAXScript is also "kind" to the user as to letting them assigning different value classes and performs the operations on them, if possible.)</p>
<p>MEL:<br />
<code>&#123;<br />
&nbsp;&nbsp;&nbsp;proc int sumTheNumbers(int $num1,int $num2)<br />
&nbsp;&nbsp;&nbsp;&#123;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return $num1+$num2&#59;<br />
&nbsp;&nbsp;&nbsp;&#125;<br />
&nbsp;&nbsp;&nbsp;print(sumTheNumbers(10, 20)+"\n")&#59; // call the function with some input numbers of choice (from within a print() function in order to see the result)<br />
&nbsp;&nbsp;&nbsp;print(sumTheNumbers("You ", "can't!")+"\n")&#59; // MEL will automatically convert the input classes to integer class, if possible<br />
&#125;</code><br />
(notice that I just declared an INTEGER procedure that expects two INTEGER values to be passed to it, so, there's no way you could summarize two floats (i.e.: 10.0 and 20.0) or even strings (i.e.: "You " and "can't!") and expect MEL to return float or string values respectively. What MEL will do is it'll convert the incoming value classes to, in this case, integers, if possible, and then performs the required calculations!</p>
<p>So, there you go, these were basic and simplyfied examples of the different languages. The conclusion could be stated as Python being the superior language to MXS and MEL and its syntax being most conformable to MAXScript (or rather the oposite, MAXScript being very conformable o Python, as MAXscript is younger). There are, of course, much, much deeper differences or similarities that wasn't the purpose of this article to bring up. I'm yet to learn Python more deeply myself, so I can't name more concrete, deeper, differences among the languages. However, if you're facing the same problem (which language to learn) coming from 3ds max, I'd recommend both, MEL and Python. I learnt MEL marginally just to get a glimpse of how it works and how it treats user input and then I went to Python for its much cleaner and easier syntax and much wider possibilities.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/im-loving-python/feed</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
	</channel>
</rss>
