<?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>Technical Art for Games &#187; Bugs</title>
	<atom:link href="http://adammechtley.com/tag/bugs/feed/" rel="self" type="application/rss+xml" />
	<link>http://adammechtley.com</link>
	<description>Tips, Tutorials, and Tools - by Adam Mechtley</description>
	<lastBuildDate>Wed, 14 Jul 2010 02:27:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>MSyntax.enableQuery() and MSyntax.enableEdit() Break Object Parsing</title>
		<link>http://adammechtley.com/2010/01/msyntax-enablequery-and-msyntax-enableedit-break-object-parsing/</link>
		<comments>http://adammechtley.com/2010/01/msyntax-enablequery-and-msyntax-enableedit-break-object-parsing/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 06:41:26 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Maya Python]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Bugs]]></category>
		<category><![CDATA[Command]]></category>
		<category><![CDATA[Maya]]></category>
		<category><![CDATA[Undocumented]]></category>

		<guid isPermaLink="false">http://adammechtley.com/?p=573</guid>
		<description><![CDATA[In Maya, many built-in commands support any of three modes: create, edit, and query. Although it may not be immediately obvious, each of these modes has some particularities that set them apart, and which consequently require some extra effort on the part of the programmer to support. Maya does have some built-in support, which is [...]]]></description>
			<content:encoded><![CDATA[<p>In Maya, many built-in commands support any of three modes: create, edit, and query. Although it may not be immediately obvious, each of these modes has some particularities that set them apart, and which consequently require some extra effort on the part of the programmer to support. Maya does have some built-in support, which is presently only partially functional, so it is helpful to understand what it actually gains you to use it and work around its issues.<br />
<span id="more-573"></span><br />
Consider the <code>polySphere</code> command in MEL as an example:</p>
<p><strong>Create Mode:</strong></p>
<pre class="code">polySphere -n "newSphere" -r 5;
polySphere -n "otherSphere" -r 2;</pre>
<p>This creates two polygon sphere objects with the specified radii.</p>
<p><strong>Edit Mode:</strong></p>
<pre class="code">polySphere -e -r 1 newSphere otherSphere;</pre>
<p>Try though you might, edit mode only works on one object at a time. In this case, the edit will only be applied to newSphere.</p>
<p><strong>Query Mode:</strong></p>
<pre class="code">polySphere -q -r newSphere otherSphere;</pre>
<p>Just as is the case in edit mode, trying to specify multiple objects does not work—you can only query one object and one attribute at a time. Moreover, while the -r flag typically requires a decimal number, it requires no argument in query mode.</p>
<p>Fundamentally then, you as a programmer have two somewhat tedious problems to solve:</p>
<ol>
<li>How do I make my command throw an error in create/edit modes when there is no argument specified, but not in query mode?</li>
<li>How do I make my command require an object in edit and query modes, but not in create mode?</li>
</ol>
<p>In Complete Maya Programming, David Gould writes:</p>
<blockquote><p>The various modes are simply a convention used to describe when certain operations can and can&#8217;t be performed. Since the operations of creating, editing, and querying are so common, they have been given their own convention that all commands should follow. The standard convention is that if a command supports querying and editing, it adds the query and edit flags. These are defined in their short and long forms as -q/query and -e/edit, respectively. (334-335)</p></blockquote>
<p>Though this may have been the case at the time that Gould wrote, the API has included special functions for dealing with these modes at least as far back as version 8.5, so they are accessible to Python in all versions with official support. Specifically, the API includes <a href="http://download.autodesk.com/us/maya/2010help/API/class_m_syntax.html#410dd274062a09c42c4408800608fb3a">MSyntax.enableQuery()</a> and <a href="http://download.autodesk.com/us/maya/2010help/API/class_m_syntax.html#5ad50dd986e8ac8f1c230eefc0755f80">MSyntax.enableEdit()</a> as part of the syntax definition. Calling these functions in the syntax creator does a couple of things:</p>
<ol>
<li>Automatically adds the edit/query flags to the syntax definition, consequently permitting the use of the <a href="http://download.autodesk.com/us/maya/2010help/API/class_m_arg_parser.html#c686baf47950d9d1c8dfd4f18f88b00b">MArgParser.isEdit()</a> and <a href="http://download.autodesk.com/us/maya/2010help/API/class_m_arg_parser.html#63817d4c39c80aa7bc5eb92593de694a">MArgParser.isQuery()</a> functions</li>
<li>Automatically handles problem number 1 above by throwing descriptive errors<sup>&dagger;</sup> when <a href="http://download.autodesk.com/us/maya/2010help/API/class_m_arg_database.html#00f67ce6fa6f70b5be4803f6406afc0d">constructing the MArgDatabase object using the custom syntax</a></li>
</ol>
<p>However, there are a couple of problems. Typically, you can rely on your MArgDatabase construction to catch a variety of syntax errors and provide the user with valuable information.<sup>&dagger;</sup> For example, you can specify a minimum number of objects in your syntax creator that your command requires:</p>
<pre class="code">syntax.setObjectType(OM.MSyntax.kSelectionList, 1) # the command requires a minimum of 1 object</pre>
<p>Using this function call, you can reliably parse arguments in your <code>doIt()</code> function like this:</p>
<pre class="code">try:
    argData = OM.MArgDatabase(self.syntax(), args) # if this fails, it will raise its own exception...
except:
    pass # ...so we can just pass here
else:
    # Do cool stuff here</pre>
<p>&#8230;and get a descriptive error message in MEL<sup>&dagger;</sup> like this if you try to invoke the command without supplying any objects:</p>
<pre class="code">// Error: line 1: This command requires at least 1 argument(s) to be specified or selected;  found 0. //</pre>
<p>If you try to implement edit and query modes fully manually, as David Gould suggests, then this same technique still works. However, if you use <a href="http://download.autodesk.com/us/maya/2010help/API/class_m_syntax.html#410dd274062a09c42c4408800608fb3a">MSyntax.enableQuery()</a> or <a href="http://download.autodesk.com/us/maya/2010help/API/class_m_syntax.html#5ad50dd986e8ac8f1c230eefc0755f80">MSyntax.enableEdit()</a> to add these modes, then <strong>they will not respect your minimum object requirements!</strong> You can therefore run into problems where your command tries to work with an object in the selection list, but it does not exist because Maya&#8217;s built-in error-trapping did not catch the problem. Consequently, you need to add an additional, manual check when you parse your arguments. It could look something like this:</p>
<pre class="code"># parse the arguments
try:
	argData = OM.MArgDatabase(self.syntax(), args) # if this fails, it will raise its own exception...
except:
	pass # ...so we can just pass here
else:
	# manually confirm the object list
	sList = OM.MSelectionList()
	argData.getObjects(sList)
	if (argData.isEdit() or argData.isQuery()) and sList.length() is not 1:
		sys.stderr.write ("ERROR: This command requires exactly 1 argument to be specified or selected;  found 0.")
		sys.exit()
	# Do cool stuff here</pre>
<p>In the end, there is (at least presently) still some manual work required, though these simple function calls do go some way in helping you easily support additional command modes.</p>
<p><sup>&dagger;</sup>Presently, the Command Engine only throws descriptive syntax errors when a command is invoked from MEL. Invoking with a syntax error from Python simply prints no message, though the dysfunction will be contained.</p>
]]></content:encoded>
			<wfw:commentRss>http://adammechtley.com/2010/01/msyntax-enablequery-and-msyntax-enableedit-break-object-parsing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problems with allNodeTypes Command</title>
		<link>http://adammechtley.com/2009/12/problems-with-allnodetypes-command/</link>
		<comments>http://adammechtley.com/2009/12/problems-with-allnodetypes-command/#comments</comments>
		<pubDate>Thu, 31 Dec 2009 21:48:39 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[MEL]]></category>
		<category><![CDATA[Maya Python]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Bugs]]></category>
		<category><![CDATA[Maya]]></category>
		<category><![CDATA[Node]]></category>
		<category><![CDATA[Undocumented]]></category>

		<guid isPermaLink="false">http://adammechtley.com/?p=545</guid>
		<description><![CDATA[Oftentimes, when loading your own custom tool set, you may want to confirm the existence of a plug-in on the client machine in order to prevent weird errors. Specifically, if you create a tool that works with a custom node, you may want to verify the node&#8217;s existence using the allNodeTypes command. Unfortunately, this command [...]]]></description>
			<content:encoded><![CDATA[<p>Oftentimes, when loading your own custom tool set, you may want to confirm the existence of a plug-in on the client machine in order to prevent weird errors. Specifically, if you create a tool that works with a custom node, you may want to verify the node&#8217;s existence using the <code>allNodeTypes</code> command. Unfortunately, this command has a really quirky problem when used in Python.<br />
<span id="more-545"></span><br />
The first thing worth mentioning is that this command is undocumented in all current versions of Maya with Python support (8.5, 2008, 2009, and 2010). Thus, you are using it at your own risk. Nonetheless, because it can be really useful, we should risk it! The command basically returns a list of all <em>specific</em> node types registered in the Maya session. I say &#8220;specific&#8221; here because it doesn&#8217;t return un-creatable parent classes for nodes (e.g. dagObject), but rather only those those which can be created using the <code>createNode</code> command. Consequently, you may want to search this list for your custom node and load its plug-in file if the node is not registered in the current session.</p>
<p>While the command seems to behave as expected in MEL, it does <em>not</em> currently work as expected in Python. Namely, if you first call this command from Python, then the first time it is called it will return <code>None</code>. Thus, to work around this problem, you should either first call the command from MEL, or make the first invocation form Python a dummy, as in this example:</p>
<pre class="code">__allNodes__ = cmds.allNodeTypes() # This returns None
__allNodes__ = cmds.allNodeTypes() # This returns the list and can therefore be used throughout your module</pre>
]]></content:encoded>
			<wfw:commentRss>http://adammechtley.com/2009/12/problems-with-allnodetypes-command/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Problems with MItSelectionList Filters</title>
		<link>http://adammechtley.com/2009/12/problems-with-mitselectionlist-filters/</link>
		<comments>http://adammechtley.com/2009/12/problems-with-mitselectionlist-filters/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 06:10:08 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Maya Python]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Bugs]]></category>
		<category><![CDATA[Maya]]></category>

		<guid isPermaLink="false">http://www.adammechtley.com/?p=509</guid>
		<description><![CDATA[One of the most common tools in the Maya API for custom commands is the MItSelectionList class. Part of the reason why it is so valuable is because it allows for an optional filter in its constructor using the MFn::Type enum. Applying a filter allows us to effectively ignore certain types of objects in which [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most common tools in the Maya API for custom commands is the MItSelectionList class. Part of the reason why it is so valuable is because it allows for an optional filter in its <a title="Constructor function for MItSelectionList in the Maya API" href="http://download.autodesk.com/us/maya/2010help/API/class_m_it_selection_list.html#c06387e5c128fcc869562caf20bef1d9">constructor</a> using the <a title="Maya API documentation for MFn::Type enum" href="http://download.autodesk.com/us/maya/2010help/API/class_m_fn.html#a89f9fd6c3157993508e460683cc948b">MFn::Type enum</a>. Applying a filter allows us to effectively ignore certain types of objects in which we are not interested, and conceivably to code with some amount of impunity since we know what the objects inside the iterator will be. Conceivably&#8230;<br />
<span id="more-509"></span><br />
While working on some custom commands for the book over the weekend, I discovered some cases in which the filters do not work as expected, so be on the lookout!</p>
<p>Specifically, you might presume that using the MFn.kDagNode or the MFn.kTransform filter should limit the iterator to objects of type <a title = "Maya API documentation for the MItSelectionList::sellItemType enum" href="http://download.autodesk.com/us/maya/2010help/API/class_m_it_selection_list.html#be4d283ac9f6e6b587c73786653b9a35">kDagSelection</a>. In the former case, this could still include shape nodes, while the latter case properly excludes them. The problem, however, is that the iterator will still include objects of type kPlugSelection, presumably because plugs are technically part of a dependency node. As such, while a transform or any other DAG object could be captured using <a title="Maya API documentation for MItSelectionList.getDagPath()" href="http://download.autodesk.com/us/maya/2010help/API/class_m_it_selection_list.html#52eb9f98a3996bbacde98940f5d84abe">MItSelectionList.getDagPath()</a>, you can get a difficult-to-find error if a plug has snuck into your selection somehow.</p>
<p>Although you can handle this problem in a variety of ways (such as including a check against the selection item type), I recommend instead using the <a href="http://download.autodesk.com/us/maya/2010help/API/class_m_it_selection_list.html#00af993ad0fd64f92850b26c80276906">getDependNode()</a> function to get the node on which the plug exists, and then use a function set to get a a DAG path to this node. I have made a simple Python script so you can see the problem as well as a possible solution:</p>
<pre class="code"><code>import maya.OpenMaya as OM
import maya.cmds as cmds

locator1 = cmds.spaceLocator()
mathNode = cmds.createNode('multMatrix')
locator2 = cmds.spaceLocator()

sList = OM.MSelectionList()
sList.add(locator1[0])
sList.add('%s%s'%(locator1[0],'.rotateX'))
sList.add(mathNode)
sList.add(locator2[0])
sList.add('locatorShape%s'%locator2[0].lstrip('locator'))

sListAsStrings = []
sList.getSelectionStrings(sListAsStrings)
print 'List: %s'%sListAsStrings

iter = OM.MItSelectionList(sList, OM.MFn.kDagNode)
node = OM.MObject()
path = OM.MDagPath()
items = {0:'kDagSelectionItem',
    1:'kAnimSelectionItem',
    2:'kDNselectionItem',
    3:'kPlugSelectionItem'}

while not iter.isDone():
    iter.getDependNode(node)
    OM.MFnDagNode(node).getPath(path)
    print '------------'
    print 'Item Type: %s'%(items[iter.itemType()])
    print 'Dependency Node: %s'%OM.MFnDependencyNode(node).name()
    print 'DAG Path: %s'%path.partialPathName()
    iter.next()</code></pre>
<p>You should end up with something like:</p>
<pre class="code"><code>List: [u'locator1', u'locator1.rotateX', u'multMatrix4', u'locator2', u'locatorShape2']
------------
Item Type: kDagSelectionItem
Dependency Node: locator1
DAG Path: locator1
------------
Item Type: kPlugSelectionItem
Dependency Node: locator1
DAG Path: locator1
------------
Item Type: kDagSelectionItem
Dependency Node: locator2
DAG Path: locator2
------------
Item Type: kDagSelectionItem
Dependency Node: locatorShape2
DAG Path: locatorShape2</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://adammechtley.com/2009/12/problems-with-mitselectionlist-filters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting up your PYTHONPATH environment variable globally on OSX</title>
		<link>http://adammechtley.com/2009/10/setting-up-your-pythonpath-environment-variable-globally-on-osx/</link>
		<comments>http://adammechtley.com/2009/10/setting-up-your-pythonpath-environment-variable-globally-on-osx/#comments</comments>
		<pubDate>Fri, 02 Oct 2009 18:29:00 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[General Interest]]></category>
		<category><![CDATA[Maya Python]]></category>
		<category><![CDATA[Bugs]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Maya]]></category>
		<category><![CDATA[OSX]]></category>

		<guid isPermaLink="false">http://www.adammechtley.com/?p=459</guid>
		<description><![CDATA[Here&#8217;s another time-saver for OSX users. Don&#8217;t use environment.plist for global environment variables! When you want to add locations to your Python path, you have a couple of different options. Ryan talked about this in greater detail on his site, so I won&#8217;t go into the details for all of these. If you want to [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s another time-saver for OSX users. Don&#8217;t use <a href="http://developer.apple.com/mac/library/qa/qa2001/qa1067.html">environment.plist</a> for global environment variables!<br />
<span id="more-459"></span><br />
When you want to add locations to your Python path, you have a couple of different options. Ryan talked about this in <a title="Importing modules and changing your Python path for Maya" href="http://www.rtrowbridge.com/blog/2008/11/27/maya-python-import-scripts/">greater detail</a> on his site, so I won&#8217;t go into the details for all of these. If you want to permanently add locations to your path, you have three general alternatives:</p>
<ol>
<li>Use sys.path.append() in your userSetup.py file</li>
<li>Set the value for PYTHONPATH in your maya.env file</li>
<li>Set the value for PYTHONPATH at the system level</li>
</ol>
<p><a href="http://download.autodesk.com/us/maya/2010help/index.html?url=Python_Python_in_Maya.htm,topicNumber=d0e181290"><br />
Autodesk&#8217;s documentation</a> can help you figure out the first two methods reasonably well, and they work fine for most situations. However, if you have locations you want to use with Maya as well as other interpreters, the third option may be helpful. While doing this on Windows is relatively easy, it is a little painful on Mac OSX.</p>
<p>Most Google searching will send you to some variation on <a title="The bad way to set up an environment variable on OSX" href="http://www.astro.washington.edu/users/rowen/AquaEnvVar.html">this technique</a>, whereby you create an environment.plist file containing the value for your PYTHONPATH variable and place it in a folder ~/.MacOSX. Maybe this will work for you, but maybe it won&#8217;t. It didn&#8217;t work for me. What&#8217;s the problem?</p>
<p>Apparently, when you start an application from Spotlight as opposed to Finder, it has a different parent process—one that does not use the environment.plist file. I have gotten used to using Spotlight to start all of my applications and to perform the majority of my menu operations because it saves me huge amounts of time while working (and I don&#8217;t want to have to remember where stuff is). Fortunately, there is a fix that will ensure your environment variables will be properly set in all contexts. I suggest you <a title="How to set up a global environment variable in OSX the right way" href="http://www.digitaledgesw.com/node/31">read about the details</a> if you are interested, but if you just want to work then use the following solution:</p>
<ol>
<li>If you do not have a launchd.conf file in /etc then create one</li>
<li>Edit launchd.conf to contain a line like this: <code>setenv PYTHONPATH /Users/Shared/Autodesk/maya/scripts</code></li>
<li>Reboot</li>
</ol>
<p>You can now confirm that this has worked by opening Terminal from Spotlight and entering the <code>set</code> command.</p>
]]></content:encoded>
			<wfw:commentRss>http://adammechtley.com/2009/10/setting-up-your-pythonpath-environment-variable-globally-on-osx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
