Kristine Middlemiss's ActivityTypepadTypepadtag:typepad.com,2003:profile.typepad.com/services/activity/atom/tag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://activitystrea.ms/schema/1.0/personhttp://profile.typepad.com/6p0120a5aeb1d3970ctag:api.typepad.com,2009:6e0120a5aeb1d3970c0177445c2908970d Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-08-27T09:08:00Ztag:api.typepad.com,2009:6a0163057a21c8970d016769456972970bCreating a New Attribute from MPlughttp://activitystrea.ms/schema/1.0/article2012-08-27T09:08:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>Have you ever wanted to create a new attribute from the definition of an existing one, such as kTransform? However you cannot get the proper type from the attribute since MDataHanle::type() returns kInvalid:</p> <pre class="brush: cpp; toolbar: false;"> // Create attribute for future access MDataHandle hData =plug.asMDataHandle(); MFnTypedAttribute typedAttr; MFnAttribute fnAttr; fnAttr.setObject( plug.attribute() ); MString sName =fnAttr.name(); MString sShortName =fnAttr.shortName(); MFnData::Type type =hData.type(); MObject newAttr =typedAttr.create( sName, sShortName, type, MObject::kNullObj, &st ); if ( MS::kSuccess == st ) { // Add a dynamic attribute to procfx st = MFnDependencyNode( pNode-&gt;thisMObject() ).addAttribute( newAttr, MFnDependencyNode::kLocalDynamicAttr ); if ( MS::kSuccess != st ) { assert( false ); } } </pre> <p>MDataHandle will only give you information about the data currently in an attribute, not about the attribute itself. A generic attribute may accept multiple data types.</p> <p>Along a similar vein, attributes of more complex types, such as kMesh, often don't have a default values. If such an attribute has not yet been given a value, then MDataHandle will come back empty, with a type of kInvalid.</p> <p>So you really need to stick with MFnAttribute and its derivatives, as well as the various Maya commands for querying attributes: attributeQuery, attributeInfo and getAttr.</p> <p>For the specific task you're trying to perform - copying an existing attribute from one node to another - the simplest approach is to use MFnAttribute::getAddAttrCmd() to get the 'addAttr' command required to recreate the source attribute, then apply that command to the target node.</p> <p>Failing that, you can take an MObject containing the attribute to be copied, call its apiType() method and compare that against the various attribute type constants in MFn.h (kNumericAttribute, kDoubleAngleAttribute, kEnumAttribute, etc). Then load the attribute into the corresponding functionset (MFnNumericAttribute, MFnUnitAttribute, MFnEnumAttribute, etc) which will allow you query the remaining info you need to recreate the attribute on another node.</p> <p>One place where this latter approach may get tricky is if the attribute is using a plug-in data type. MObject::apiType() will return MFn::kTypedAttribute, but I don't know of any sure-fire way of determining the MTypeId of the data type, other than going back to MFnAttribute::getAddAttrCmd() and parsing it out of the returned command string.</p> <p>You could use MDataHandle::typeId(), but as I pointed out above you might end up getting kInvalid back if the attribute does not yet have a value. What we should really do here is add an attrTypeId() method to MFnTypedAttribute because MFnTypedAttribute has two versions of its create() method: one takes an MFnData constant and creates an attribute of the corresponding standard data type, the other takes an MTypeId and is used to create an attribute of the corresponding plugin data type...one day....</p> <p>Enjoy,</p> <p>Kristine</p> <p>Have you ever wanted to create a new attribute from the definition of an existing one, such as kTransform? However you cannot get the proper type from the attribute since MDataHanle::type() returns kInvalid:</p> <pre class="brush: cpp; toolbar: false;"> // Create attribute for future access MDataHandle hData =plug.asMDataHandle(); MFnTypedAttribute typedAttr; MFnAttribute fnAttr; fnAttr.setObject( plug.attribute() ); MString sName =fnAttr.name(); MString sShortName =fnAttr.shortName(); MFnData::Type type =hData.type(); MObject newAttr =typedAttr.create( sName, sShortName, type, MObject::kNullObj, &st ); if ( MS::kSuccess == st ) { // Add a dynamic attribute to procfx st = MFnDependencyNode( pNode-&gt;thisMObject() ).addAttribute( newAttr, MFnDependencyNode::kLocalDynamicAttr ); if ( MS::kSuccess != st ) { assert( false ); } } </pre> <p>MDataHandle will only give you information about the data currently in an attribute, not about the attribute itself. A generic attribute may accept multiple data types.</p> <p>Along a similar vein, attributes of more complex types, such as kMesh, often don't have a default values. If such an attribute has not yet been given a value, then MDataHandle will come back empty, with a type of kInvalid.</p> <p>So you really need to stick with MFnAttribute and its derivatives, as well as the various Maya commands for querying attributes: attributeQuery, attributeInfo and getAttr.</p> <p>For the specific task you're trying to perform - copying an existing attribute from one node to another - the simplest approach is to use MFnAttribute::getAddAttrCmd() to get the 'addAttr' command required to recreate the source attribute, then apply that command to the target node.</p> <p>Failing that, you can take an MObject containing the attribute to be copied, call its apiType() method and compare that against the various attribute type constants in MFn.h (kNumericAttribute, kDoubleAngleAttribute, kEnumAttribute, etc). Then load the attribute into the corresponding functionset (MFnNumericAttribute, MFnUnitAttribute, MFnEnumAttribute, etc) which will allow you query the remaining info you need to recreate the attribute on another node.</p> <p>One place where this latter approach may get tricky is if the attribute is using a plug-in data type. MObject::apiType() will return MFn::kTypedAttribute, but I don't know of any sure-fire way of determining the MTypeId of the data type, other than going back to MFnAttribute::getAddAttrCmd() and parsing it out of the returned command string.</p> <p>You could use MDataHandle::typeId(), but as I pointed out above you might end up getting kInvalid back if the attribute does not yet have a value. What we should really do here is add an attrTypeId() method to MFnTypedAttribute because MFnTypedAttribute has two versions of its create() method: one takes an MFnData constant and creates an attribute of the corresponding standard data type, the other takes an MTypeId and is used to create an attribute of the corresponding plugin data type...one day....</p> <p>Enjoy,</p> <p>Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c017c3168927a970b Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-08-22T09:15:02Ztag:api.typepad.com,2009:6a0163057a21c8970d017617365257970cAdding a Custom Cursor in MCursor in Mayahttp://activitystrea.ms/schema/1.0/article2012-08-22T09:15:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>To create a custom cursor when using MPxContext::SetCursor, a cursor requires two XBM images: one for the mask, which defines which bits are transparent and which opaque, and one for the color, which defines which bits are white and which are black.</p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017617364f1a970c-pi" style="display: inline;"><img alt="Cursor" border="0" class="asset asset-image at-xid-6a0163057a21c8970d017617364f1a970c image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017617364f1a970c-800wi" title="Cursor" /></a></p> <p>If you look at an XBM image file you&#39;ll see that it&#39;s just a snippet of C code which defines macros giving the width and height of the image, and an array of unsigned char. E.g:</p> <p>#define HtumbleCursorMask_width 16<br />#define HtumbleCursorMask_height 16<br />static unsigned char HtumbleCursorMask_bits[] = {<br />&#0160; 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0xdf, 0xf8, 0xff, 0x3c, 0xf8, 0x1e, 0xf8,<br />&#0160; 0x1e, 0xfc, 0x00, 0xfc, 0x7e, 0x00, 0x7e, 0xf0, 0x3e, 0xf0, 0x3e, 0x78,<br />&#0160; 0xfe, 0x3f, 0xf6, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, };</p> <p>So you can include the two XBM image files directly into the C++ source for your plug-in, and then pass the sizes and arrays to the MCursor constructor.</p> <p>This will only work if the XBM image is known at compile time and doesn&#39;t change. If you want to dynamically create a cursor at runtime from an arbitrary pair of XBM files then you would have to either write some code to parse the information from the files or find a library routine to do it for you. It&#39;s probably possible to do it with the Qt&#39;s image classes (QImage, QBitmap, QPixmap) but I haven&#39;t tried it myself.</p> <p>One suggestion I have heard is overriding an existing cursor by replacing the contents of the header files,&#0160;however this&#0160;will not work for these reasons:</p> <p>1) The header files were only read when Maya was built, not at runTime. They&#39;re not even shipped to you.</p> <p>2) Since the switch to Qt we no longer use those XBM files for cursors. Instead we use PNG files. There should be a constructor for MCursor which takes a PNG file, but we don&#39;t yet have that.</p> <p>3) Even the PNG files which Maya now uses are only used when Maya is built and do not get shipped to you. Their contents are embedded into a Qt resource file. So overriding the PNGs won&#39;t work, either.</p> <p>An example of a custom cursor is in the Devkit sample lassoTool.</p> <p>Here is the required XBM information:</p> <p>Files used for:<br />Cursors</p> <p>File Format:<br />xbm</p> <p>Requirements:<br />16x16<br />transparent background</p> <p>Created with this application:<br />xpaint</p> <p>Naming conventions:<br />H&lt;name&gt;Cursor.h<br />H&lt;name&gt;CursorMask.h</p> <p>Where used:<br />Mouse pointer</p> <p>Enjoy,</p> <p>Kristine</p> <p>To create a custom cursor when using MPxContext::SetCursor, a cursor requires two XBM images: one for the mask, which defines which bits are transparent and which opaque, and one for the color, which defines which bits are white and which are black.</p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017617364f1a970c-pi" style="display: inline;"><img alt="Cursor" border="0" class="asset asset-image at-xid-6a0163057a21c8970d017617364f1a970c image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017617364f1a970c-800wi" title="Cursor" /></a></p> <p>If you look at an XBM image file you&#39;ll see that it&#39;s just a snippet of C code which defines macros giving the width and height of the image, and an array of unsigned char. E.g:</p> <p>#define HtumbleCursorMask_width 16<br />#define HtumbleCursorMask_height 16<br />static unsigned char HtumbleCursorMask_bits[] = {<br />&#0160; 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0xdf, 0xf8, 0xff, 0x3c, 0xf8, 0x1e, 0xf8,<br />&#0160; 0x1e, 0xfc, 0x00, 0xfc, 0x7e, 0x00, 0x7e, 0xf0, 0x3e, 0xf0, 0x3e, 0x78,<br />&#0160; 0xfe, 0x3f, 0xf6, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, };</p> <p>So you can include the two XBM image files directly into the C++ source for your plug-in, and then pass the sizes and arrays to the MCursor constructor.</p> <p>This will only work if the XBM image is known at compile time and doesn&#39;t change. If you want to dynamically create a cursor at runtime from an arbitrary pair of XBM files then you would have to either write some code to parse the information from the files or find a library routine to do it for you. It&#39;s probably possible to do it with the Qt&#39;s image classes (QImage, QBitmap, QPixmap) but I haven&#39;t tried it myself.</p> <p>One suggestion I have heard is overriding an existing cursor by replacing the contents of the header files,&#0160;however this&#0160;will not work for these reasons:</p> <p>1) The header files were only read when Maya was built, not at runTime. They&#39;re not even shipped to you.</p> <p>2) Since the switch to Qt we no longer use those XBM files for cursors. Instead we use PNG files. There should be a constructor for MCursor which takes a PNG file, but we don&#39;t yet have that.</p> <p>3) Even the PNG files which Maya now uses are only used when Maya is built and do not get shipped to you. Their contents are embedded into a Qt resource file. So overriding the PNGs won&#39;t work, either.</p> <p>An example of a custom cursor is in the Devkit sample lassoTool.</p> <p>Here is the required XBM information:</p> <p>Files used for:<br />Cursors</p> <p>File Format:<br />xbm</p> <p>Requirements:<br />16x16<br />transparent background</p> <p>Created with this application:<br />xpaint</p> <p>Naming conventions:<br />H&lt;name&gt;Cursor.h<br />H&lt;name&gt;CursorMask.h</p> <p>Where used:<br />Mouse pointer</p> <p>Enjoy,</p> <p>Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c0177442e7e99970d Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-08-17T09:08:00Ztag:api.typepad.com,2009:6a0163057a21c8970d017743fb5d23970dIntroduction to MotionBuilder OpenReality SDK Programming DevTV Videohttp://activitystrea.ms/schema/1.0/article2012-08-17T09:08:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>I have just recently completed a MotionBuilder DevTV, called “Introduction to MotionBuilder OpenReality SDK Programming”.</p> <p>This is located on the public Autodesk MotionBuilder Developer Center page, under the title DevTV:</p> <p><a href="http://www.autodesk.com/developmotionbuilder">http://www.autodesk.com/developmotionbuilder</a></p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743fb5849970d-pi" style="display: inline;"></a> <a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743fb5907970d-pi" style="display: inline;"><img alt="Dfd" border="0" class="asset asset-image at-xid-6a0163057a21c8970d017743fb5907970d image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743fb5907970d-800wi" title="Dfd" /></a></p> <p>This is a quick start guide (1.5 hours), the primary goal is:</p> <ul> <li>How to sit down and write your first plug-in</li> <li>Learn the general structure and capability of the SDK</li> <li>Where to go to find out more</li> </ul> <p>The target audience for this DevTV material:</p> <ul> <li>Familiar with the MotionBuilder&#0160;product </li> <li>Has some programming experience, but not necessarily an expert </li> <li>Has never before seen the SDK I am presenting </li> </ul> <p>Enjoy!</p> <p>Kristine<br /><br /></p> <p>I have just recently completed a MotionBuilder DevTV, called “Introduction to MotionBuilder OpenReality SDK Programming”.</p> <p>This is located on the public Autodesk MotionBuilder Developer Center page, under the title DevTV:</p> <p><a href="http://www.autodesk.com/developmotionbuilder">http://www.autodesk.com/developmotionbuilder</a></p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743fb5849970d-pi" style="display: inline;"></a> <a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743fb5907970d-pi" style="display: inline;"><img alt="Dfd" border="0" class="asset asset-image at-xid-6a0163057a21c8970d017743fb5907970d image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743fb5907970d-800wi" title="Dfd" /></a></p> <p>This is a quick start guide (1.5 hours), the primary goal is:</p> <ul> <li>How to sit down and write your first plug-in</li> <li>Learn the general structure and capability of the SDK</li> <li>Where to go to find out more</li> </ul> <p>The target audience for this DevTV material:</p> <ul> <li>Familiar with the MotionBuilder&#0160;product </li> <li>Has some programming experience, but not necessarily an expert </li> <li>Has never before seen the SDK I am presenting </li> </ul> <p>Enjoy!</p> <p>Kristine<br /><br /></p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c01774419b73a970d Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-08-13T09:08:04Ztag:api.typepad.com,2009:6a0163057a21c8970d016768d56bd5970bWhat's a callback and what's its purpose?http://activitystrea.ms/schema/1.0/article2012-08-13T09:08:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>A callback is something you can setup to watch a specific behaviour, and when that behaviour is performed you do something special which is out of the normal behaviour or functionality of MotionBuilder (or Maya).</p> <p>Here is my everyday English example of a callbacks :)</p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017616ca6b54970c-pi" style="display: inline;"><img alt="Images" border="0" class="asset asset-image at-xid-6a0163057a21c8970d017616ca6b54970c" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017616ca6b54970c-800wi" title="Images" /></a><br />You assign me to watch a front door, and when people come in the door I hand them a visitor pass, without me watching the front door people would just come through the door and never get a visitors pass.</p> <ul> <li>Kristine = callback</li> <li>front door = MotionBuilder</li> <li>visitor pass = is the something special behaviour</li> </ul> <p>So in MotionBuilder (or Maya), let’s say I want everyone to follow a special naming convention for their scene files,&#0160;then I would set up a callback to watch anytime someone creates a new file. Then when this happens&#0160;MotionBuilder calls a function in my code to save the file with a special name.</p> <p>A very important thing to point out is that callbacks are efficient in MotionBuilder and Maya,&#0160;so you do not need to be concerned, that they will&#0160;slow down the application even though a callback is always watching what you told it to watch.</p> <p>Callbacks allow you to add&#0160;an personal level of customization to your production, studio or project. Since we cannot anticipate all&#0160;the different usages of callbacks we just keep it very open where you can monitor most things in MotionBuilder and Maya. But having&#0160;said this,&#0160;this also means you must set the callbacks up yourself, since the combination of things to watch and&#0160;things to do could be endless.</p> <p>Another example is when someone changes a property, you maybe want to give them a warning…but how will you know when the user changes the property? They could do it at any time during their session usage, and you want the warning to be triggered right after they change it, not at a hard coded point of time... so here is where you want to setup a callback on property values, that will output a warning when this occurs.</p> <p>Enjoy,</p> <p>Kristine</p> <p>&#0160;</p> <p>A callback is something you can setup to watch a specific behaviour, and when that behaviour is performed you do something special which is out of the normal behaviour or functionality of MotionBuilder (or Maya).</p> <p>Here is my everyday English example of a callbacks :)</p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017616ca6b54970c-pi" style="display: inline;"><img alt="Images" border="0" class="asset asset-image at-xid-6a0163057a21c8970d017616ca6b54970c" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017616ca6b54970c-800wi" title="Images" /></a><br />You assign me to watch a front door, and when people come in the door I hand them a visitor pass, without me watching the front door people would just come through the door and never get a visitors pass.</p> <ul> <li>Kristine = callback</li> <li>front door = MotionBuilder</li> <li>visitor pass = is the something special behaviour</li> </ul> <p>So in MotionBuilder (or Maya), let’s say I want everyone to follow a special naming convention for their scene files,&#0160;then I would set up a callback to watch anytime someone creates a new file. Then when this happens&#0160;MotionBuilder calls a function in my code to save the file with a special name.</p> <p>A very important thing to point out is that callbacks are efficient in MotionBuilder and Maya,&#0160;so you do not need to be concerned, that they will&#0160;slow down the application even though a callback is always watching what you told it to watch.</p> <p>Callbacks allow you to add&#0160;an personal level of customization to your production, studio or project. Since we cannot anticipate all&#0160;the different usages of callbacks we just keep it very open where you can monitor most things in MotionBuilder and Maya. But having&#0160;said this,&#0160;this also means you must set the callbacks up yourself, since the combination of things to watch and&#0160;things to do could be endless.</p> <p>Another example is when someone changes a property, you maybe want to give them a warning…but how will you know when the user changes the property? They could do it at any time during their session usage, and you want the warning to be triggered right after they change it, not at a hard coded point of time... so here is where you want to setup a callback on property values, that will output a warning when this occurs.</p> <p>Enjoy,</p> <p>Kristine</p> <p>&#0160;</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c01761717d6d6970c Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-08-08T09:08:03Ztag:api.typepad.com,2009:6a0163057a21c8970d017743fb25bf970dSmall Annoying Things Maya Forumhttp://activitystrea.ms/schema/1.0/article2012-08-08T09:08:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p><strong>Please help us identify things that bother you when you’re working in Maya that we can easily fix.</strong></p> <p><a href="http://mayafeedback.autodesk.com/forums/160518-small-annoying-things-to-fix-in-maya-forum">http://mayafeedback.autodesk.com/forums/160518-small-annoying-things-to-fix-in-maya-forum</a>&#0160;</p> <p>Suggest and vote for annoying little quirks or problems in Maya you want us to fix, and get others to vote for your ideas.<br /><br />Describe both the steps to show the issue, and how you would prefer it. Enter each idea separately (we’ll remove items with multiple ideas).<br /><br />Put larger issues in the <a href="http://mayaautodesk.uservoice.com/forums/160514-ideas-for-maya-forum">Ideas for Maya</a> forum. We’ll move issues that are not small (even if they are annoying) to this forum — if so, you’ll get your votes back.</p> <p>There is a &quot;scripting and api&quot; category,&#0160;there you can&#0160;add your&#0160;small annoying things for the Python or C++ API :)</p> <p>Enjoy,</p> <p>Kristine</p> <p><strong>Please help us identify things that bother you when you’re working in Maya that we can easily fix.</strong></p> <p><a href="http://mayafeedback.autodesk.com/forums/160518-small-annoying-things-to-fix-in-maya-forum">http://mayafeedback.autodesk.com/forums/160518-small-annoying-things-to-fix-in-maya-forum</a>&#0160;</p> <p>Suggest and vote for annoying little quirks or problems in Maya you want us to fix, and get others to vote for your ideas.<br /><br />Describe both the steps to show the issue, and how you would prefer it. Enter each idea separately (we’ll remove items with multiple ideas).<br /><br />Put larger issues in the <a href="http://mayaautodesk.uservoice.com/forums/160514-ideas-for-maya-forum">Ideas for Maya</a> forum. We’ll move issues that are not small (even if they are annoying) to this forum — if so, you’ll get your votes back.</p> <p>There is a &quot;scripting and api&quot; category,&#0160;there you can&#0160;add your&#0160;small annoying things for the Python or C++ API :)</p> <p>Enjoy,</p> <p>Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c0167690537aa970b Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-08-03T09:08:00Ztag:api.typepad.com,2009:6a0163057a21c8970d016768d5221a970bWhat do I mean by a “handle”…?http://activitystrea.ms/schema/1.0/article2012-08-03T09:08:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>Through my years at Autodesk/Alias, I have done a lot of teaching and education (some is recorded and some is not), but some things you might catch me saying during training are… “Now you get the handle to the object”, or “this now returns the handle to the object”, but what the heck does that really mean? I will know try to explain my colloquialism below using MotionBuilder Python SDK code as an example.</p> <h2>A Handle in Programming Terms</h2> <p>What I mean by a handle is what the constructor of a class returns when you create an object.</p> <p>For example:</p> <p><span style="color: #008000;">&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; from</span> <span style="color: #0000ff;">pyfbsdk</span> <span style="color: #008000;">import</span> <span style="color: #666666;">*</span></p> <p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; lModel <span style="color: #666666;">=</span> FBModelCube(<span style="color: #ba2121;">&quot;Kristine&quot;</span>)</p> <p>Here lModel is&#0160;the &quot;handle&quot; to&#0160;the FBModelCube object instance/copy. In this specific case you have your class definition of FBModelCube which would has been originally created by the MotionBuilder developers (we only let you create copies of this class, so you do not mess with the original version).</p> <p>Once you have a &quot;handle&quot; to the object you want to have in your scene/file,&#0160;you can use the class functions and attributes on your new copy to manipulate your copy.</p> <p>The concept &quot;handle&quot; is more of a visual naming convention than anything else, think of it like a door handle to hold onto the copy/instance of your FBModelCube object so that you can work with it.&#0160;</p> <p>See this will still create an object:</p> <p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; FBModelCube(<span style="color: #ba2121;">&quot;Kristine&quot;</span>)</p> <p>But since you didn’t assign a variable to hold the handle to your object you would not be able to access it for further manipulation.</p> <p>But if you choose to use a function from the instance of the copy such as GetSelectedPointsCount (), like this:</p> <p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; pointCount = lModel.GetSelectedPointCount()</p> <p>pointCount is not a handle to the instance, it is just an integer holding the SelectedPointCount, where lModel is the handle to the object.</p> <p>Just to clarify, handles can only be created when you create an instance of the class in the Python Reference Guide, such as FBModelCube. The documentation called these ‘constructors’.</p> <p>This concept is applicable to any object oriented programming language, this would fall into MotionBuilder SDK, Maya API, Mudbox SDK, FBX SDK, and Softimage SDK (and 3ds Max SDK)!</p> <p>Enjoy,</p> <p>Kristine</p> <p>Through my years at Autodesk/Alias, I have done a lot of teaching and education (some is recorded and some is not), but some things you might catch me saying during training are… “Now you get the handle to the object”, or “this now returns the handle to the object”, but what the heck does that really mean? I will know try to explain my colloquialism below using MotionBuilder Python SDK code as an example.</p> <h2>A Handle in Programming Terms</h2> <p>What I mean by a handle is what the constructor of a class returns when you create an object.</p> <p>For example:</p> <p><span style="color: #008000;">&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; from</span> <span style="color: #0000ff;">pyfbsdk</span> <span style="color: #008000;">import</span> <span style="color: #666666;">*</span></p> <p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; lModel <span style="color: #666666;">=</span> FBModelCube(<span style="color: #ba2121;">&quot;Kristine&quot;</span>)</p> <p>Here lModel is&#0160;the &quot;handle&quot; to&#0160;the FBModelCube object instance/copy. In this specific case you have your class definition of FBModelCube which would has been originally created by the MotionBuilder developers (we only let you create copies of this class, so you do not mess with the original version).</p> <p>Once you have a &quot;handle&quot; to the object you want to have in your scene/file,&#0160;you can use the class functions and attributes on your new copy to manipulate your copy.</p> <p>The concept &quot;handle&quot; is more of a visual naming convention than anything else, think of it like a door handle to hold onto the copy/instance of your FBModelCube object so that you can work with it.&#0160;</p> <p>See this will still create an object:</p> <p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; FBModelCube(<span style="color: #ba2121;">&quot;Kristine&quot;</span>)</p> <p>But since you didn’t assign a variable to hold the handle to your object you would not be able to access it for further manipulation.</p> <p>But if you choose to use a function from the instance of the copy such as GetSelectedPointsCount (), like this:</p> <p>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; pointCount = lModel.GetSelectedPointCount()</p> <p>pointCount is not a handle to the instance, it is just an integer holding the SelectedPointCount, where lModel is the handle to the object.</p> <p>Just to clarify, handles can only be created when you create an instance of the class in the Python Reference Guide, such as FBModelCube. The documentation called these ‘constructors’.</p> <p>This concept is applicable to any object oriented programming language, this would fall into MotionBuilder SDK, Maya API, Mudbox SDK, FBX SDK, and Softimage SDK (and 3ds Max SDK)!</p> <p>Enjoy,</p> <p>Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c017616dea95c970c Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-07-30T09:08:00Ztag:api.typepad.com,2009:6a0163057a21c8970d016768d4cfed970bLooking at undo in regards to deleting attributes and nodeshttp://activitystrea.ms/schema/1.0/article2012-07-30T09:08:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>Today, I want to talk about the recommended way of handling the deletion of attributes and nodes within Maya through the wise guidance of Dean Edmonds (Autodesk Maya API Architect). We will examine this potential solution for this scenario:</p> <p style="text-align: left;"><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d016768d4beec970b-pi" style="display: inline;"><img alt="Image" border="0" class="asset asset-image at-xid-6a0163057a21c8970d016768d4beec970b image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d016768d4beec970b-800wi" title="Image" /></a><br />Let’s say you have plug-in that has a connection to a user defined attributes on other objects in a scene. You may write some code that detects that if the node is deleted, then the user defined attributes on the connected objects are deleted.</p> <p>One way to do this maybe through the passThroughToOne() method and in there you traverse the graph to the connected nodes. Then using the executeCommandOnIdle() method run the MEL command deleteAttr on the unwanted attribute, which supports undo.</p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743b00a30970d-pi" style="display: inline;"><img alt="Image" border="0" class="asset asset-image at-xid-6a0163057a21c8970d017743b00a30970d image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743b00a30970d-800wi" title="Image" /></a><br />Let’s examine some better ways, as well as looking at the downfalls. Let&#39;s define some terminology first. When I say &quot;deleteNode command&quot; I mean whatever command caused your node to be deleted. When I say &quot;deleteAttr command&quot; I mean the &#39;deleteAttr&#39; your node is trying to execute when it is deleted.</p> <p>Potentially you could use executeCommandOnIdle(), however this would cause a problem. If you executed the deleteAttr command immediately then it should end up being included in the same undo chunk as the deleteNode command.</p> <p>So the first question is to ask is why are you using executeCommandOnIdle() rather than just executeCommand() and see if there are other ways of addressing those problems.</p> <p>However if you really do need to do the deleteAttr command using executeCommandOnIdle() then you can use the &#39;undoInfo -stateWithoutFlush off&#39; command to temporarily disable the undo queue just before doing the deletion, then &#39;undoInfo -stateWithoutFlush on&#39; immediately after. E.g:</p> <p>&#0160;&#0160;&#0160; MString cmd = MString( &quot;undoInfo -swf off; deleteAttr &quot;) + attrName + &quot;; undoInfo -swf on;&quot;;<br />&#0160;&#0160;&#0160; MGlobal::executeCommandOnIdle(cmd);</p> <p>The one thing to point out though, is you need to be very careful, that no other scene-modifying commands execute while the undo queue is off.</p> <p>You will then need a way to restore the deleted attribute when the deleteNode command is undone. There are a couple of ways of doing that. The most flexible is probably to create an MPxCommand which does nothing in its doIt() but restores the attribute in its redoIt(). So when your node is deleted, it would do something like this:</p> <p>&#0160;&#0160;&#0160; MString cmd = MString(&quot;myRestoreAttr &quot;) + attrName;<br />&#0160;&#0160;&#0160; MGlobal::executeCommand(cmd, false, true /* add it to the undo queue */);</p> <p>&#0160;&#0160;&#0160; cmd = MString( &quot;undoInfo -swf off; deleteAttr &quot;) + attrName + &quot;; undoInfo -swf on;&quot;;<br />&#0160;&#0160;&#0160; MGlobal::executeCommandOnIdle(cmd);</p> <p>When the node is deleted, &#39;myRestoreAttr&#39; command will be executed. It won&#39;t do anything but it will be added to the same undo chunk as the deleteNode command.</p> <p>Then, during the next idle cycle, the attribute will be deleted.</p> <p>When the deleteNode command is undone, it will undo the &#39;myRestoreAttr&#39; command, which will add the attr back onto the target node.</p> <p>There are some potential problems with this approach:</p> <p>1) The timing might not work out. The attribute needs to be restored before the deleteNode command attempts to reconnect your node to it. That will all depend upon how you detect the node deletion. Hopefully one of MNodeMessage::addNodeAboutToDeleteCallback() or addNodePreRemovalCallback() will do the trick.</p> <p>2) The attribute disconnection done by the deleteNode command may use the attribute&#39;s internal pointer for the reconnection, not its name, in which case Maya will probably crash. To get around that, rather than using a &#39;deleteAttr&#39; command to delete the attribute, use another MPxCommand which uses an MDGModifier to delete it. It would share that MDGModifier with the &#39;myRestoreAttr&#39; command which could then use it to undo the attribute deletion. That way it&#39;s still the same original attribute being restored and Maya&#39;s internal pointers to it will still be valid.</p> <p>3) There&#39;s no guarantee that the idle command will have had a chance to execute before the node deletion is undone. That means that &#39;myRestoreAttr&#39; may be called while the attribute is still there. Note that the MDGModifier solution to problem 2 above will take care of this since undoing an MDGModifier which hasn&#39;t been done yet will have no effect.</p> <p>4) The fact that the idle command may not be called before the node deletion is undone also means that it might execute *after* the node deletion has been undone. So if you are not careful you will end up trying to delete the attribute while your node is still connected to it. How you address that depends upon how your code is set up, but it should be pretty straightforward.</p> <p>Enjoy,</p> <p>Kristine</p> <p>Today, I want to talk about the recommended way of handling the deletion of attributes and nodes within Maya through the wise guidance of Dean Edmonds (Autodesk Maya API Architect). We will examine this potential solution for this scenario:</p> <p style="text-align: left;"><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d016768d4beec970b-pi" style="display: inline;"><img alt="Image" border="0" class="asset asset-image at-xid-6a0163057a21c8970d016768d4beec970b image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d016768d4beec970b-800wi" title="Image" /></a><br />Let’s say you have plug-in that has a connection to a user defined attributes on other objects in a scene. You may write some code that detects that if the node is deleted, then the user defined attributes on the connected objects are deleted.</p> <p>One way to do this maybe through the passThroughToOne() method and in there you traverse the graph to the connected nodes. Then using the executeCommandOnIdle() method run the MEL command deleteAttr on the unwanted attribute, which supports undo.</p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743b00a30970d-pi" style="display: inline;"><img alt="Image" border="0" class="asset asset-image at-xid-6a0163057a21c8970d017743b00a30970d image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017743b00a30970d-800wi" title="Image" /></a><br />Let’s examine some better ways, as well as looking at the downfalls. Let&#39;s define some terminology first. When I say &quot;deleteNode command&quot; I mean whatever command caused your node to be deleted. When I say &quot;deleteAttr command&quot; I mean the &#39;deleteAttr&#39; your node is trying to execute when it is deleted.</p> <p>Potentially you could use executeCommandOnIdle(), however this would cause a problem. If you executed the deleteAttr command immediately then it should end up being included in the same undo chunk as the deleteNode command.</p> <p>So the first question is to ask is why are you using executeCommandOnIdle() rather than just executeCommand() and see if there are other ways of addressing those problems.</p> <p>However if you really do need to do the deleteAttr command using executeCommandOnIdle() then you can use the &#39;undoInfo -stateWithoutFlush off&#39; command to temporarily disable the undo queue just before doing the deletion, then &#39;undoInfo -stateWithoutFlush on&#39; immediately after. E.g:</p> <p>&#0160;&#0160;&#0160; MString cmd = MString( &quot;undoInfo -swf off; deleteAttr &quot;) + attrName + &quot;; undoInfo -swf on;&quot;;<br />&#0160;&#0160;&#0160; MGlobal::executeCommandOnIdle(cmd);</p> <p>The one thing to point out though, is you need to be very careful, that no other scene-modifying commands execute while the undo queue is off.</p> <p>You will then need a way to restore the deleted attribute when the deleteNode command is undone. There are a couple of ways of doing that. The most flexible is probably to create an MPxCommand which does nothing in its doIt() but restores the attribute in its redoIt(). So when your node is deleted, it would do something like this:</p> <p>&#0160;&#0160;&#0160; MString cmd = MString(&quot;myRestoreAttr &quot;) + attrName;<br />&#0160;&#0160;&#0160; MGlobal::executeCommand(cmd, false, true /* add it to the undo queue */);</p> <p>&#0160;&#0160;&#0160; cmd = MString( &quot;undoInfo -swf off; deleteAttr &quot;) + attrName + &quot;; undoInfo -swf on;&quot;;<br />&#0160;&#0160;&#0160; MGlobal::executeCommandOnIdle(cmd);</p> <p>When the node is deleted, &#39;myRestoreAttr&#39; command will be executed. It won&#39;t do anything but it will be added to the same undo chunk as the deleteNode command.</p> <p>Then, during the next idle cycle, the attribute will be deleted.</p> <p>When the deleteNode command is undone, it will undo the &#39;myRestoreAttr&#39; command, which will add the attr back onto the target node.</p> <p>There are some potential problems with this approach:</p> <p>1) The timing might not work out. The attribute needs to be restored before the deleteNode command attempts to reconnect your node to it. That will all depend upon how you detect the node deletion. Hopefully one of MNodeMessage::addNodeAboutToDeleteCallback() or addNodePreRemovalCallback() will do the trick.</p> <p>2) The attribute disconnection done by the deleteNode command may use the attribute&#39;s internal pointer for the reconnection, not its name, in which case Maya will probably crash. To get around that, rather than using a &#39;deleteAttr&#39; command to delete the attribute, use another MPxCommand which uses an MDGModifier to delete it. It would share that MDGModifier with the &#39;myRestoreAttr&#39; command which could then use it to undo the attribute deletion. That way it&#39;s still the same original attribute being restored and Maya&#39;s internal pointers to it will still be valid.</p> <p>3) There&#39;s no guarantee that the idle command will have had a chance to execute before the node deletion is undone. That means that &#39;myRestoreAttr&#39; may be called while the attribute is still there. Note that the MDGModifier solution to problem 2 above will take care of this since undoing an MDGModifier which hasn&#39;t been done yet will have no effect.</p> <p>4) The fact that the idle command may not be called before the node deletion is undone also means that it might execute *after* the node deletion has been undone. So if you are not careful you will end up trying to delete the attribute while your node is still connected to it. How you address that depends upon how your code is set up, but it should be pretty straightforward.</p> <p>Enjoy,</p> <p>Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c016768bb9bac970b Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-07-25T09:41:00Ztag:api.typepad.com,2009:6a0163057a21c8970d017616add16b970cSetting a user event within Mayahttp://activitystrea.ms/schema/1.0/article2012-07-25T09:41:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>I was looking through some interesting questions that have come into ADN in the past, and thought I would share this one, it was about the possibility of setting a user event with a scriptJob (Maya Command).</p> <p>There are no MEL commands to create user events and the scriptJob command cannot be used to wait for them.</p> <p>However, you can do both in a Python script using API calls.</p> <p>Here&#39;s how you would register a new user event type called &#39;myEvent&#39;:</p> <p>&#0160;&#0160;&#0160;&#0160;<span style="color: #0000ff;">import</span> maya.OpenMaya <span style="color: #0000ff;">as</span> om<br />&#0160;&#0160;&#0160; om.MUserEventMessage.registerUserEvent<span style="color: #ff0000;">(</span><span style="color: #80c0ff;">&#39;myEvent&#39;</span><span style="color: #ff0000;">)</span></p> <p>To have a function called &#39;myFunc&#39; execute whenever the event occurs:</p> <p>&#0160;&#0160;&#0160;&#0160;<span style="color: #0000ff;">def</span> myFunc<span style="color: #ff0000;">(</span>data<span style="color: #ff0000;">):</span><br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; print<span style="color: #ff0000;">(</span><span style="color: #80c0ff;">&#39;Got a myEvent event!&#39;</span><span style="color: #ff0000;">)</span></p> <p>&#0160;&#0160;&#0160; callbackId =om.MUserEventMessage.addUserEventCallback<span style="color: #ff0000;">(</span><span style="color: #80c0ff;">&#39;myEvent&#39;</span>, myFunc<span style="color: #ff0000;">)</span></p> <p>To send a &#39;myEvent&#39; event:</p> <p>&#0160;&#0160;&#0160; om.MUserEventMessage.postUserEvent<span style="color: #ff0000;">(</span><span style="color: #80c0ff;">&#39;myEvent&#39;</span><span style="color: #ff0000;">)</span></p> <p>To remove the callback function when done:</p> <p>&#0160;&#0160; &#0160;om.MUserEventMessage.removeCallback<span style="color: #ff0000;">(</span>callbackId<span style="color: #ff0000;">)</span></p> <p>Enjoy</p> <p>~Kristine</p> <p>I was looking through some interesting questions that have come into ADN in the past, and thought I would share this one, it was about the possibility of setting a user event with a scriptJob (Maya Command).</p> <p>There are no MEL commands to create user events and the scriptJob command cannot be used to wait for them.</p> <p>However, you can do both in a Python script using API calls.</p> <p>Here&#39;s how you would register a new user event type called &#39;myEvent&#39;:</p> <p>&#0160;&#0160;&#0160;&#0160;<span style="color: #0000ff;">import</span> maya.OpenMaya <span style="color: #0000ff;">as</span> om<br />&#0160;&#0160;&#0160; om.MUserEventMessage.registerUserEvent<span style="color: #ff0000;">(</span><span style="color: #80c0ff;">&#39;myEvent&#39;</span><span style="color: #ff0000;">)</span></p> <p>To have a function called &#39;myFunc&#39; execute whenever the event occurs:</p> <p>&#0160;&#0160;&#0160;&#0160;<span style="color: #0000ff;">def</span> myFunc<span style="color: #ff0000;">(</span>data<span style="color: #ff0000;">):</span><br />&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160; print<span style="color: #ff0000;">(</span><span style="color: #80c0ff;">&#39;Got a myEvent event!&#39;</span><span style="color: #ff0000;">)</span></p> <p>&#0160;&#0160;&#0160; callbackId =om.MUserEventMessage.addUserEventCallback<span style="color: #ff0000;">(</span><span style="color: #80c0ff;">&#39;myEvent&#39;</span>, myFunc<span style="color: #ff0000;">)</span></p> <p>To send a &#39;myEvent&#39; event:</p> <p>&#0160;&#0160;&#0160; om.MUserEventMessage.postUserEvent<span style="color: #ff0000;">(</span><span style="color: #80c0ff;">&#39;myEvent&#39;</span><span style="color: #ff0000;">)</span></p> <p>To remove the callback function when done:</p> <p>&#0160;&#0160; &#0160;om.MUserEventMessage.removeCallback<span style="color: #ff0000;">(</span>callbackId<span style="color: #ff0000;">)</span></p> <p>Enjoy</p> <p>~Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c0167689f4871970b Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-07-20T10:05:00Ztag:api.typepad.com,2009:6a0163057a21c8970d017743432248970dUsing a MEL/Python Script to Load Plug-Inshttp://activitystrea.ms/schema/1.0/article2012-07-20T10:05:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>You may come across a time where you want to tell Maya to load/unload a plug-in during &quot;plug-in load time&quot; (i.e. while Maya is launching) or maybe you have certain plug-ins that conflict with each other, and you would like to have an automatic way of unloading (or &quot;not&quot; loading) various plug-ins.</p> <p>To go about doing this there are four options, I highly recommend option 1, as it is the most perdictable and safest.</p> <h3>Option 1: Using Maya API</h3> <p>Within the class MSceneMessage there are callbacks for monitoring plug-in loading:</p> <ol> <li>kBeforePluginLoad</li> <li>kAfterPluginLoad</li> <li>kBeforePluginUnload</li> <li>kAfterPluginUnload</li> </ol> <p>Whether you use the method addCallback which just allows you to add additional functionality after one of the above actions or you use the method addCheckCallback which allows you to abort the above actions all together and have Maya do something different (like load another plug-in).</p> <h3>Option 2: Modifying userPrefs.mel</h3> <p>Maya determines which plug-ins should be loaded or not from the userPrefs.mel file (found in the folder: /username/maya/x.x/prefs/). The lines that do this are at the bottom of the file. They go something like: evalDeferred(&quot;autoLoadPlugin( ..... ); So a simple but messy solution is to comment out the lines which load plug-ins you don&#39;t want loaded, in the userPrefs.mel file.</p> <h3>Option 3: Modifying initialPluginLoad.mel</h3> <p>If the first solution is too messy and is not automated (i.e. you have to re-edit the userPrefs.mel file each time), another possible but solution is to edit the file: /scripts/startup/initialPluginLoad.mel and add something like this at the end of the initialPluginLoad function: if (`exists userPluginLoad`) eval &quot;source userPluginLoad&quot;; Then put userPluginLoad.mel somewhere on your script path, and this script file should contain something like:</p> <p>if (`about -batch`)<br /> {<br /> &#0160;&#0160;&#0160; catch(`loadPlugin &quot;batchPlugin1&quot;`);<br /> &#0160;&#0160;&#0160; catch(`loadPlugin &quot;batchPlugin2&quot;`);<br /> &#0160;&#0160;&#0160; // ...<br /> }<br /> else<br /> {<br /> &#0160;&#0160;&#0160; catch(`loadPlugin &quot;interactivePlugin1&quot;`);<br /> &#0160;&#0160;&#0160; catch(`loadPlugin &quot;interactivePlugin2&quot;`); <br /> &#0160;&#0160;&#0160; // ...<br /> }</p> <p>By doing this, please note the following:</p> <ul> <li>This bypasses the standard autoload feature of plug-ins. If you set a plug-in to autoload, it will be loaded before Maya gets to userPluginLoad.mel.</li> <li>These files normally should NOT be edited, and great caution must be taken if you decide to proceed in doing so.</li> <li>The userPluginLoad.mel script should just be MEL code, not a MEL procedure. The above example assumes that sourcing the script will do all the work. </li> </ul> <h3>Option 4: Modifying autoLoadPlugin.mel</h3> <p>Plug-ins that are set to autoload are loaded by the MEL script &quot;autoLoadPlugin.mel&quot;. This script is actually invoked directly from C++ code or by the user&#39;s preference file, so there is no easy way that you can avoid having this script invoked... BUT you can change what it does. If you rewrite autoLoadPlugin.mel to simply ignore some plug-ins if Maya is in batch mode, then you may be able to do what you want. The other alternative is to modify the user&#39;s preferences (userPrefs.mel) to remove the offending autoLoadPlugin command, as indicated in the first solution. This is more complicated because you have to restore the user&#39;s preferences again, after you are done with the batch mode. It may not be too bad, if all you&#39;ve got to do is use the `system` MEL command to invoke OS shell command (e.g. cp, mv, etc...) to create a &quot;backup&quot; of the original prefs to restore in the end.</p> <p>Enjoy,</p> <p>Kristine</p> <p>You may come across a time where you want to tell Maya to load/unload a plug-in during &quot;plug-in load time&quot; (i.e. while Maya is launching) or maybe you have certain plug-ins that conflict with each other, and you would like to have an automatic way of unloading (or &quot;not&quot; loading) various plug-ins.</p> <p>To go about doing this there are four options, I highly recommend option 1, as it is the most perdictable and safest.</p> <h3>Option 1: Using Maya API</h3> <p>Within the class MSceneMessage there are callbacks for monitoring plug-in loading:</p> <ol> <li>kBeforePluginLoad</li> <li>kAfterPluginLoad</li> <li>kBeforePluginUnload</li> <li>kAfterPluginUnload</li> </ol> <p>Whether you use the method addCallback which just allows you to add additional functionality after one of the above actions or you use the method addCheckCallback which allows you to abort the above actions all together and have Maya do something different (like load another plug-in).</p> <h3>Option 2: Modifying userPrefs.mel</h3> <p>Maya determines which plug-ins should be loaded or not from the userPrefs.mel file (found in the folder: /username/maya/x.x/prefs/). The lines that do this are at the bottom of the file. They go something like: evalDeferred(&quot;autoLoadPlugin( ..... ); So a simple but messy solution is to comment out the lines which load plug-ins you don&#39;t want loaded, in the userPrefs.mel file.</p> <h3>Option 3: Modifying initialPluginLoad.mel</h3> <p>If the first solution is too messy and is not automated (i.e. you have to re-edit the userPrefs.mel file each time), another possible but solution is to edit the file: /scripts/startup/initialPluginLoad.mel and add something like this at the end of the initialPluginLoad function: if (`exists userPluginLoad`) eval &quot;source userPluginLoad&quot;; Then put userPluginLoad.mel somewhere on your script path, and this script file should contain something like:</p> <p>if (`about -batch`)<br /> {<br /> &#0160;&#0160;&#0160; catch(`loadPlugin &quot;batchPlugin1&quot;`);<br /> &#0160;&#0160;&#0160; catch(`loadPlugin &quot;batchPlugin2&quot;`);<br /> &#0160;&#0160;&#0160; // ...<br /> }<br /> else<br /> {<br /> &#0160;&#0160;&#0160; catch(`loadPlugin &quot;interactivePlugin1&quot;`);<br /> &#0160;&#0160;&#0160; catch(`loadPlugin &quot;interactivePlugin2&quot;`); <br /> &#0160;&#0160;&#0160; // ...<br /> }</p> <p>By doing this, please note the following:</p> <ul> <li>This bypasses the standard autoload feature of plug-ins. If you set a plug-in to autoload, it will be loaded before Maya gets to userPluginLoad.mel.</li> <li>These files normally should NOT be edited, and great caution must be taken if you decide to proceed in doing so.</li> <li>The userPluginLoad.mel script should just be MEL code, not a MEL procedure. The above example assumes that sourcing the script will do all the work. </li> </ul> <h3>Option 4: Modifying autoLoadPlugin.mel</h3> <p>Plug-ins that are set to autoload are loaded by the MEL script &quot;autoLoadPlugin.mel&quot;. This script is actually invoked directly from C++ code or by the user&#39;s preference file, so there is no easy way that you can avoid having this script invoked... BUT you can change what it does. If you rewrite autoLoadPlugin.mel to simply ignore some plug-ins if Maya is in batch mode, then you may be able to do what you want. The other alternative is to modify the user&#39;s preferences (userPrefs.mel) to remove the offending autoLoadPlugin command, as indicated in the first solution. This is more complicated because you have to restore the user&#39;s preferences again, after you are done with the batch mode. It may not be too bad, if all you&#39;ve got to do is use the `system` MEL command to invoke OS shell command (e.g. cp, mv, etc...) to create a &quot;backup&quot; of the original prefs to restore in the end.</p> <p>Enjoy,</p> <p>Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c017743656c57970d Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-07-16T09:03:03Ztag:api.typepad.com,2009:6a0163057a21c8970d016768676575970bAll Things Qthttp://activitystrea.ms/schema/1.0/article2012-07-16T09:03:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>Okay, let me re-phrase that, “All Things Qt….and Maya” :)</p> <p>In the past couple of years I have been getting more and more interested and into Qt, why you ask? Because it’s fun to develop things that are visual! I am what you would call a “Visual Learner” if I can see it or picture it with my mind’s eye, and then I will understand it a lot quicker! And reason two; there are Python wrappers for Qt!!! (Need I say more ;)…? But seriously, they make it pretty easy to create custom UI, and who doesn’t like easy!</p> <p>(I am having a bit of picture envy from Cyrille’s post so I will try to spice mine up a bit)</p> <p>First I am going to pimp myself out, and go over my resources that hopefully you will find helpful and education on how to tackle Qt in Maya.</p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d0176165c3728970c-pi" style="display: inline;"><img alt="Df" border="0" class="asset asset-image at-xid-6a0163057a21c8970d0176165c3728970c image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d0176165c3728970c-800wi" title="Df" /></a></p> <p>The AREA AU Masterclass home page: <a href="http://area.autodesk.com/masterclasses*">http://area.autodesk.com/masterclasses*</a>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;</p> <ul> <li>To view any of the Masterclasses you will have to sign-up for a free AREA login, so if you don’t have one you will not be able to view the links below until you log in.</li> </ul> <h3><strong>Oh my… Maya is Qt || Masterclass</strong></h3> <p>If you are diving into Qt in Maya, you will find there really isn’t a lot of resources available, which was the reasoning behind this training is called “Oh my… Maya is Qt”. This one hour video is an overview of all the different Qt technologies/ways to work with Maya in Qt, depending on your programming level and skills you can pick from my video what best suits you!</p> <p><strong>Agenda</strong></p> <ul> <li>Introducing Qt</li> <li>How Qt fits into Maya</li> <li>&#0160;Ways to work with Qt &#0160; <ul> <li>Qt Designer</li> <li>PyQt/PySide</li> <li>Maya API</li> <li>Qt SDK </li> </ul> </li> </ul> <p><strong>Viewing Location: </strong></p> <ul> <li>The AREA &gt; AU Masterclass &gt; <a href="http://area.autodesk.com/masterclasses/masterclass/class2_q4_2011">Oh my… Maya is Qt</a></li> <li> <span class="asset asset-generic at-xid-6a0163057a21c8970d016768675f60970b"><a href="http://around-the-corner.typepad.com/files/sample-files.zip">Download Sample Files</a></span></li> </ul> <h3><strong>The Wonderful World of PyQt, PySide and Autodesk Maya || Masterclass</strong></h3> <p>Hot off the press! In this Masterclass I focused specifically on PyQt and PySide and how to work with them in Maya. This one hour video go into specifically compares the two Python Qt frameworks, and which is the best of you, looking at the pro’s and con’s, as well as it comes along with some real world samples.</p> <p><strong>Agenda</strong></p> <ul> <li>How Qt fits into Maya</li> <li>What is PySide and PyQt</li> <li>How PySide and PyQt fit into Maya</li> <li>Why use PyQt/PySide in Maya</li> <li>PyQt vs. PySide</li> <li>Working with PyQt</li> <li>Working with PySide</li> <li>Resources</li> </ul> <p><strong>Viewing Location: </strong></p> <ul> <li>The AREA &gt; AU Masterclass &gt; <a href="http://area.autodesk.com/masterclasses/masterclass/class2_q2_2012_kristine_middlemiss">The Wonderful World of PyQt, PySide and Autodesk Maya</a></li> <li> <span class="asset asset-generic at-xid-6a0163057a21c8970d017743425014970d"><a href="http://around-the-corner.typepad.com/files/maya_pyqt_pyside_samples_kmiddlemiss.zip">Download Sample Files</a></span></li> </ul> <h3><strong>Advanced Graphical User Interfaces with Qt || Book Chapter</strong></h3> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d0176165c4344970c-pi" style="display: inline;"><img alt="Xd" border="0" class="asset asset-image at-xid-6a0163057a21c8970d0176165c4344970c" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d0176165c4344970c-800wi" title="Xd" /></a><br /><strong></strong><br /> I got the unique opportunity to participate and write a chapter for the newest Maya API text book, called <strong>Maya Python for Games and Film: A Complete Reference for Maya Python and the Maya Python API</strong> , my chapter was chapter 8 <strong>Advanced Graphical User Interfaces with Qt. </strong>I was approached by the author Adam,(our paths had crossed, a few years back, in a training course), this was a great experience and I definitely learned a lot about publishing, especially how much work it is, so kudos to all authors and editors.</p> <ul> <li>Adam Mechtley and Ryan Trowbridge. <strong>Maya Python for Games and Film: A Complete Reference for Maya Python and the Maya Python API</strong>. Morgan Kaufmann, 2011. ISBN-10: 0123785782 </li> <li><a href="http://www.maya-python.com/">Companion Site</a></li> </ul> <p>Enjoy,</p> <p>Kristine</p> <ul> </ul> <p>Okay, let me re-phrase that, “All Things Qt….and Maya” :)</p> <p>In the past couple of years I have been getting more and more interested and into Qt, why you ask? Because it’s fun to develop things that are visual! I am what you would call a “Visual Learner” if I can see it or picture it with my mind’s eye, and then I will understand it a lot quicker! And reason two; there are Python wrappers for Qt!!! (Need I say more ;)…? But seriously, they make it pretty easy to create custom UI, and who doesn’t like easy!</p> <p>(I am having a bit of picture envy from Cyrille’s post so I will try to spice mine up a bit)</p> <p>First I am going to pimp myself out, and go over my resources that hopefully you will find helpful and education on how to tackle Qt in Maya.</p> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d0176165c3728970c-pi" style="display: inline;"><img alt="Df" border="0" class="asset asset-image at-xid-6a0163057a21c8970d0176165c3728970c image-full" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d0176165c3728970c-800wi" title="Df" /></a></p> <p>The AREA AU Masterclass home page: <a href="http://area.autodesk.com/masterclasses*">http://area.autodesk.com/masterclasses*</a>&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;&#0160;</p> <ul> <li>To view any of the Masterclasses you will have to sign-up for a free AREA login, so if you don’t have one you will not be able to view the links below until you log in.</li> </ul> <h3><strong>Oh my… Maya is Qt || Masterclass</strong></h3> <p>If you are diving into Qt in Maya, you will find there really isn’t a lot of resources available, which was the reasoning behind this training is called “Oh my… Maya is Qt”. This one hour video is an overview of all the different Qt technologies/ways to work with Maya in Qt, depending on your programming level and skills you can pick from my video what best suits you!</p> <p><strong>Agenda</strong></p> <ul> <li>Introducing Qt</li> <li>How Qt fits into Maya</li> <li>&#0160;Ways to work with Qt &#0160; <ul> <li>Qt Designer</li> <li>PyQt/PySide</li> <li>Maya API</li> <li>Qt SDK </li> </ul> </li> </ul> <p><strong>Viewing Location: </strong></p> <ul> <li>The AREA &gt; AU Masterclass &gt; <a href="http://area.autodesk.com/masterclasses/masterclass/class2_q4_2011">Oh my… Maya is Qt</a></li> <li> <span class="asset asset-generic at-xid-6a0163057a21c8970d016768675f60970b"><a href="http://around-the-corner.typepad.com/files/sample-files.zip">Download Sample Files</a></span></li> </ul> <h3><strong>The Wonderful World of PyQt, PySide and Autodesk Maya || Masterclass</strong></h3> <p>Hot off the press! In this Masterclass I focused specifically on PyQt and PySide and how to work with them in Maya. This one hour video go into specifically compares the two Python Qt frameworks, and which is the best of you, looking at the pro’s and con’s, as well as it comes along with some real world samples.</p> <p><strong>Agenda</strong></p> <ul> <li>How Qt fits into Maya</li> <li>What is PySide and PyQt</li> <li>How PySide and PyQt fit into Maya</li> <li>Why use PyQt/PySide in Maya</li> <li>PyQt vs. PySide</li> <li>Working with PyQt</li> <li>Working with PySide</li> <li>Resources</li> </ul> <p><strong>Viewing Location: </strong></p> <ul> <li>The AREA &gt; AU Masterclass &gt; <a href="http://area.autodesk.com/masterclasses/masterclass/class2_q2_2012_kristine_middlemiss">The Wonderful World of PyQt, PySide and Autodesk Maya</a></li> <li> <span class="asset asset-generic at-xid-6a0163057a21c8970d017743425014970d"><a href="http://around-the-corner.typepad.com/files/maya_pyqt_pyside_samples_kmiddlemiss.zip">Download Sample Files</a></span></li> </ul> <h3><strong>Advanced Graphical User Interfaces with Qt || Book Chapter</strong></h3> <p><a class="asset-img-link" href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d0176165c4344970c-pi" style="display: inline;"><img alt="Xd" border="0" class="asset asset-image at-xid-6a0163057a21c8970d0176165c4344970c" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d0176165c4344970c-800wi" title="Xd" /></a><br /><strong></strong><br /> I got the unique opportunity to participate and write a chapter for the newest Maya API text book, called <strong>Maya Python for Games and Film: A Complete Reference for Maya Python and the Maya Python API</strong> , my chapter was chapter 8 <strong>Advanced Graphical User Interfaces with Qt. </strong>I was approached by the author Adam,(our paths had crossed, a few years back, in a training course), this was a great experience and I definitely learned a lot about publishing, especially how much work it is, so kudos to all authors and editors.</p> <ul> <li>Adam Mechtley and Ryan Trowbridge. <strong>Maya Python for Games and Film: A Complete Reference for Maya Python and the Maya Python API</strong>. Morgan Kaufmann, 2011. ISBN-10: 0123785782 </li> <li><a href="http://www.maya-python.com/">Companion Site</a></li> </ul> <p>Enjoy,</p> <p>Kristine</p> <ul> </ul>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c01774341cdd3970d Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-07-11T20:18:37Ztag:api.typepad.com,2009:6a0163057a21c8970d01774341cdce970dMaya Programming: The Beginninghttp://activitystrea.ms/schema/1.0/article2012-07-11T20:18:37Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>…Computer Programming…. Does that sound scary and yet inviting all at the same time?</p> <p>Are you ever curious to dive into programming and Maya? Are you a power user of Maya, or maybe interested in customizing or automating work flows? Are looking to take your work to the next level and challenge yourself, but not sure where to start… Here I will provide you with some places to start so you can get familiar with scripting so that you are more comfortable and less overwhelmed.</p> <p>&quot;Maya User, I would like to introduce you to the Script Editor&quot;, it is found here in the UI, with a default install it is placed at the bottom-right of the Maya application:</p> <p><img alt="ScriptEditorLocation" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0133f0d2ab37970b-800wi" /></p> <p>When you click on the Script Editor you see this UI pop-up:</p> <p><img alt="ScriptEditor" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0134841cb9c2970c-800wi" /></p> <p>The Script Editor has numerous features and functionality, the documentation covers what each button does, so look into the help documentation for more information if you are curious to know this UI (User Interface)&#0160;inside and out.</p> <p>We like to think of the Script Editor as having two halves, top half (Command History) and bottom half (Command Editor). The key now it making these two halves work for you, to help you learn how to script.</p> <p><strong>Step One: Monitoring the Command History.</strong></p> <p>Something that Maya does that is pretty special is for&#0160;almost all actions that you perform in the UI; Maya outputs the equivalent MEL command into the Command History pane of the Script Editor. Super Cool!!</p> <p>In addition the&#0160;Command History pane, displays any feedback such as results, warnings, or errors returned by Maya, which can be helpful not only when learning scripting!</p> <p>So in other words, for every work flow in the UI, it tells you the MEL solution.&#0160;In time, you&#0160;will figure out how&#0160;we get from Point A (Maya Action)&#0160;to Point B (MEL Command for the Maya Action), knowing where you are going is half the battle, doing it on your own is the other half the battle.</p> <p>If you don’t see the MEL Commands executed you need to make sure you have not suppressed them and that the History Output is selected for both MEL and Python.</p> <p><img alt="6-14-2010 10-35-41 AM" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0134841cc20b970c-800wi" /></p> <p><strong>Step Two: Piecing together code in the Command Editor.</strong></p> <p>This is where the famous copy and paste comes in handy, copy from the top panel and paste in the bottom panel to piece together your custom automation work flow.</p> <p>However this is the part where you need to be curious, and what I am mean by curious is that you&#0160;have to want to look up all the parts of the command so that you can start to learn what commands do what and what the flag and flag parameter syntax is about. This is the fundamental structure of scripting, so it’s important to understand it. To look up the different commands you can find these in the Help Documentation, hot-key F1.</p> <p>No one is expecting you to memorize anything, you don&#39;t need to pull out of your head&#0160;a MEL command at the drop of a hat, that&#39;s what command docs are for, there over 600 Maya commands so don&#39;t stress about learning them, the key is learning how to use the documentation efficiently.</p> <p>Once you get more comfortable with using Maya Commands and the syntax you can start diving into programming basics such as data types, variables, for loops, etc. With these programming structures you can create scripts that are what we like to call more intelligent, because they can do different things based on what is happening in the scene. But we will leave that for another day.</p> <p><strong>Step Three: Saving your beautiful scripts for Later.</strong></p> <p>Once you have put together a script, you can drag it into the shelf inside the Maya UI to save it for later and re-use it over and over. To complete this highlight your new script:</p> <p><img alt="6-14-2010 11-13-08 AM" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0133f0f28414970b-800wi" /></p> <p>Press the &#39;Alt&#39; key while dragging your highlighted script into the Shelf tab of your choice, you are then prompted with whether the code is MEL or Python:</p> <p><img alt="6-14-2010 11-07-22 AM" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0133f0f28d19970b-800wi" /></p> <p>The final result now is your code in the Shelf; press the new button to execute it:</p> <p><img alt="6-14-2010 11-15-26 AM" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0133f0f29629970b-800wi" /></p> <p><strong>Real World Example: Applying Step One through Three.</strong></p> <p>An example of a real life work flow could be to set up a scene the way you want it every time, so all you have to do when you come into Maya is click one button to get&#0160;all the default things you want in your scene&#0160;setup.<span style="color: black; mso-fareast-font-family: &#39;Times New Roman&#39;; mso-bidi-font-family: &#39;Courier New&#39;;"> </span></p> <p><span style="color: black; mso-fareast-font-family: &#39;Times New Roman&#39;; mso-bidi-font-family: &#39;Courier New&#39;;">If we want to ensure nothing is in the scene, let’s do a file new, and we see this line in the Script Editor, let’s copy it ‘file -f -new;’, transpose it into Python, we need to make sure we import the maya.cmds module:</span></p> <p>import maya.cmds as cmds</p> <p>cmds.file(f=True, new=True)</p> <p>Now we want to create two spheres, so we copy those MEL commands and transpose them into Python:</p> <p>cmds.polySphere (ch=True, o=True, r=27.080953)</p> <p>cmds.polySphere (ch=True, o=True, r=5.580194)</p> <p>&#0160;</p> <p>Full Script:</p> <p>&#0160;</p> <p>import maya.cmds as cmds</p> <p>cmds.file(f=True, new=True)</p> <p>cmds.polySphere (ch=True, o=True, r=27.080953)</p> <p>cmds.polySphere (ch=True, o=True, r=5.580194)</p> <p>I realize this sample is somewhat easy, but starting to script can be this easy, just remember be curious always look up flags, for example, what is the flag &#39;ch on the command PolySphere, what type of value does it take, etc.</p> <p>Enjoy</p> <p>Kristine</p> <p>…Computer Programming…. Does that sound scary and yet inviting all at the same time?</p> <p>Are you ever curious to dive into programming and Maya? Are you a power user of Maya, or maybe interested in customizing or automating work flows? Are looking to take your work to the next level and challenge yourself, but not sure where to start… Here I will provide you with some places to start so you can get familiar with scripting so that you are more comfortable and less overwhelmed.</p> <p>&quot;Maya User, I would like to introduce you to the Script Editor&quot;, it is found here in the UI, with a default install it is placed at the bottom-right of the Maya application:</p> <p><img alt="ScriptEditorLocation" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0133f0d2ab37970b-800wi" /></p> <p>When you click on the Script Editor you see this UI pop-up:</p> <p><img alt="ScriptEditor" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0134841cb9c2970c-800wi" /></p> <p>The Script Editor has numerous features and functionality, the documentation covers what each button does, so look into the help documentation for more information if you are curious to know this UI (User Interface)&#0160;inside and out.</p> <p>We like to think of the Script Editor as having two halves, top half (Command History) and bottom half (Command Editor). The key now it making these two halves work for you, to help you learn how to script.</p> <p><strong>Step One: Monitoring the Command History.</strong></p> <p>Something that Maya does that is pretty special is for&#0160;almost all actions that you perform in the UI; Maya outputs the equivalent MEL command into the Command History pane of the Script Editor. Super Cool!!</p> <p>In addition the&#0160;Command History pane, displays any feedback such as results, warnings, or errors returned by Maya, which can be helpful not only when learning scripting!</p> <p>So in other words, for every work flow in the UI, it tells you the MEL solution.&#0160;In time, you&#0160;will figure out how&#0160;we get from Point A (Maya Action)&#0160;to Point B (MEL Command for the Maya Action), knowing where you are going is half the battle, doing it on your own is the other half the battle.</p> <p>If you don’t see the MEL Commands executed you need to make sure you have not suppressed them and that the History Output is selected for both MEL and Python.</p> <p><img alt="6-14-2010 10-35-41 AM" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0134841cc20b970c-800wi" /></p> <p><strong>Step Two: Piecing together code in the Command Editor.</strong></p> <p>This is where the famous copy and paste comes in handy, copy from the top panel and paste in the bottom panel to piece together your custom automation work flow.</p> <p>However this is the part where you need to be curious, and what I am mean by curious is that you&#0160;have to want to look up all the parts of the command so that you can start to learn what commands do what and what the flag and flag parameter syntax is about. This is the fundamental structure of scripting, so it’s important to understand it. To look up the different commands you can find these in the Help Documentation, hot-key F1.</p> <p>No one is expecting you to memorize anything, you don&#39;t need to pull out of your head&#0160;a MEL command at the drop of a hat, that&#39;s what command docs are for, there over 600 Maya commands so don&#39;t stress about learning them, the key is learning how to use the documentation efficiently.</p> <p>Once you get more comfortable with using Maya Commands and the syntax you can start diving into programming basics such as data types, variables, for loops, etc. With these programming structures you can create scripts that are what we like to call more intelligent, because they can do different things based on what is happening in the scene. But we will leave that for another day.</p> <p><strong>Step Three: Saving your beautiful scripts for Later.</strong></p> <p>Once you have put together a script, you can drag it into the shelf inside the Maya UI to save it for later and re-use it over and over. To complete this highlight your new script:</p> <p><img alt="6-14-2010 11-13-08 AM" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0133f0f28414970b-800wi" /></p> <p>Press the &#39;Alt&#39; key while dragging your highlighted script into the Shelf tab of your choice, you are then prompted with whether the code is MEL or Python:</p> <p><img alt="6-14-2010 11-07-22 AM" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0133f0f28d19970b-800wi" /></p> <p>The final result now is your code in the Shelf; press the new button to execute it:</p> <p><img alt="6-14-2010 11-15-26 AM" border="0" src="http://mayastation.typepad.com/.a/6a01156fc44c77970b0133f0f29629970b-800wi" /></p> <p><strong>Real World Example: Applying Step One through Three.</strong></p> <p>An example of a real life work flow could be to set up a scene the way you want it every time, so all you have to do when you come into Maya is click one button to get&#0160;all the default things you want in your scene&#0160;setup.<span style="color: black; mso-fareast-font-family: &#39;Times New Roman&#39;; mso-bidi-font-family: &#39;Courier New&#39;;"> </span></p> <p><span style="color: black; mso-fareast-font-family: &#39;Times New Roman&#39;; mso-bidi-font-family: &#39;Courier New&#39;;">If we want to ensure nothing is in the scene, let’s do a file new, and we see this line in the Script Editor, let’s copy it ‘file -f -new;’, transpose it into Python, we need to make sure we import the maya.cmds module:</span></p> <p>import maya.cmds as cmds</p> <p>cmds.file(f=True, new=True)</p> <p>Now we want to create two spheres, so we copy those MEL commands and transpose them into Python:</p> <p>cmds.polySphere (ch=True, o=True, r=27.080953)</p> <p>cmds.polySphere (ch=True, o=True, r=5.580194)</p> <p>&#0160;</p> <p>Full Script:</p> <p>&#0160;</p> <p>import maya.cmds as cmds</p> <p>cmds.file(f=True, new=True)</p> <p>cmds.polySphere (ch=True, o=True, r=27.080953)</p> <p>cmds.polySphere (ch=True, o=True, r=5.580194)</p> <p>I realize this sample is somewhat easy, but starting to script can be this easy, just remember be curious always look up flags, for example, what is the flag &#39;ch on the command PolySphere, what type of value does it take, etc.</p> <p>Enjoy</p> <p>Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c0176162c378c970c Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-07-06T06:14:00Ztag:api.typepad.com,2009:6a0163057a21c8970d017742d3df71970dTop 10 Autodesk Maya Python API Gotchas When Getting Startedhttp://activitystrea.ms/schema/1.0/article2012-07-06T06:14:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<ol start="10"> <li><strong>Not Understanding the Difference between Python Script and Python API</strong> <br /> Maya has four programming interfaces, two of which are using the Python language. It&rsquo;s important to know the distinction between the terminology of Python Script and the Python API, because they each access different functionality within Maya (with very little overlap). The other two interfaces are Maya Embedded Language (MEL) and the C++ API. </li> </ol> <ol start="9"> <li><strong>Python Plug-in Disclosure </strong><br /> You cannot hide your Python API code from users! If you&rsquo;re a games developer looking to create Python plug-ins in-house and not worried about protecting your code, then feel free to code away. But it you want to protect, or commercialize and sell your hard work, you should consider using C++ to create your plug-ins.</li> </ol> <ol start="8"> <li><strong>Must use Autodesk Specific Version of Qt for Building PyQt</strong><br /> Building PyQt to work with Maya is a three step process. First you need to compile Qt using the Autodesk's Modified Qt Source Code (new for 2012) that is located on the Autodesk.com site. Then you need to compile SIP (generates Python bindings for C++) against your built Qt libraries. Last, you need to compile PyQt against your built SIP libraries. Check the website for the correct versions or you could have some difficulties down the road in your tools.</li> </ol> <ol start="7"> <li><strong>Awareness of Potential Python API Performance Penalties</strong><br /> In certain situations when computation involves complex or many API calls, the Python API may take a performance penalty compared to the C++ API. This is because the Python API sits on top of the C++ API. This results in an extra level of conversion through C++ and as well as Python is an interpreted language which is slower by nature. For example if you are thinking of doing a Python API shader, C++ will be the better choice, but for most other tasks Python is perfect!</li> </ol> <ol start="6"> <li><strong>Working with Multiple Versions of Maya Equals Multiple Versions of Python</strong><br /> If you are working on multiple versions of Maya, then you need to keep in mind that you will need to have multiple version of Python. Also if you are using PyQt, multiple versions of PyQt will need to be installed on your computer. As nice as it would be to use the same version of Python and PyQt for every version of Maya, it&rsquo;s just not realistic as things are always improving in the Python and PyQt releases. Keep yourself educated in the Maya documentation for the versions that are used in each major release, and on which platform.</li> </ol> <ol start="5"> <li><strong>Your Python API Code is not Working, and you cannot find the Problem </strong><br /> When working with the Python API, like all humans, you will have errors or code you want to debug; but how the heck do you debug it? Unfortunately, there are no out-of-the-box tools in Maya, but there are some good solutions available. Cyrille Fauvel from Autodesk has integrated a Maya Python debugger into the Eclipse IDE. The details are available on Autodesk.com, at the Maya Developer Center page. Dean Edmonds also from Autodesk has integrated the PDB debugger into the Script Editor within Maya by overriding the stdin and stout functions. Also, if you Google &ldquo;Python in Maya&rdquo; group you will see other solutions.</li> </ol> <ol start="4"> <li><strong>Knowing when and how to Use MScriptUtil Class</strong><br /> Many of the API methods in Maya require that one or more of their parameters be passed as pointers or references (return values can be pointers or references as well). Because Python does not have the concept of references or pointers, you will need the utility class called MScriptUtil for working with those pointers and references in Python. MScriptUtil bridges this gap between Python and its underlying C++ API. When you see the characters * or &amp; in the documentation for simple data types like integers and floats, think MScriptUtil!</li> </ol> <ol start="3"> <li><strong>The Reference Documentation is written for C++, but you are Using Python</strong><br /> If you do not know C++, at first glance the reference documentation will be very confusing!&nbsp; But don&rsquo;t worry; just put your eye blinders on to certain things when reading it. Because Python is a more simplified language than C++ (but none the less powerful), there are certain components in the documentation you can ignore. For example the class MString and MStringArray are not available in Python and instead you will work with strings as they are in native Python. Another example is that there is no MStatus class in Python and instead you will use standard Python error checking (try, except, catch). Try to think of this as having a mini translator going on in your brain, you see MStatus, so you just ignore it! </li> </ol> <ol start="2"> <li><strong>Trying to live in a Bubble and Teach Yourself Everything </strong><br /> There is no possible way to memorize or learn every single Maya API class, so don&rsquo;t be shy to use the resources available. As they say &ldquo;Be Resourceful&rdquo; and learn from others successes, mistakes and questions. Maya has been around for over ten years, and there is lots of API information out there (www.autodesk.com/developmaya). Also, you can check out the new book &ldquo;Maya Python for Games and Film: A Complete Reference for Maya Python and the Maya Python API&rdquo; by Adam Mechtley and Ryan Trowbridge.</li> </ol> <ol start="1"> <li><strong>Not Fully Grasping the Maya Architecture and How the Python API Leverages It</strong><br /> If you don&rsquo;t completely understanding the Maya architecture, command engine and the Dependency Graph, you will run into trouble as your tools get more complex. Take the time to learn these components as they are very different than any other animation product. Because of this complexity, it makes Maya more flexible and powerful than any other product. Check out the free Maya Python API webcast recording located here (www.autodesk.com/developmaya)</li> </ol> <ol start="10"> <li><strong>Not Understanding the Difference between Python Script and Python API</strong> <br /> Maya has four programming interfaces, two of which are using the Python language. It&rsquo;s important to know the distinction between the terminology of Python Script and the Python API, because they each access different functionality within Maya (with very little overlap). The other two interfaces are Maya Embedded Language (MEL) and the C++ API. </li> </ol> <ol start="9"> <li><strong>Python Plug-in Disclosure </strong><br /> You cannot hide your Python API code from users! If you&rsquo;re a games developer looking to create Python plug-ins in-house and not worried about protecting your code, then feel free to code away. But it you want to protect, or commercialize and sell your hard work, you should consider using C++ to create your plug-ins.</li> </ol> <ol start="8"> <li><strong>Must use Autodesk Specific Version of Qt for Building PyQt</strong><br /> Building PyQt to work with Maya is a three step process. First you need to compile Qt using the Autodesk's Modified Qt Source Code (new for 2012) that is located on the Autodesk.com site. Then you need to compile SIP (generates Python bindings for C++) against your built Qt libraries. Last, you need to compile PyQt against your built SIP libraries. Check the website for the correct versions or you could have some difficulties down the road in your tools.</li> </ol> <ol start="7"> <li><strong>Awareness of Potential Python API Performance Penalties</strong><br /> In certain situations when computation involves complex or many API calls, the Python API may take a performance penalty compared to the C++ API. This is because the Python API sits on top of the C++ API. This results in an extra level of conversion through C++ and as well as Python is an interpreted language which is slower by nature. For example if you are thinking of doing a Python API shader, C++ will be the better choice, but for most other tasks Python is perfect!</li> </ol> <ol start="6"> <li><strong>Working with Multiple Versions of Maya Equals Multiple Versions of Python</strong><br /> If you are working on multiple versions of Maya, then you need to keep in mind that you will need to have multiple version of Python. Also if you are using PyQt, multiple versions of PyQt will need to be installed on your computer. As nice as it would be to use the same version of Python and PyQt for every version of Maya, it&rsquo;s just not realistic as things are always improving in the Python and PyQt releases. Keep yourself educated in the Maya documentation for the versions that are used in each major release, and on which platform.</li> </ol> <ol start="5"> <li><strong>Your Python API Code is not Working, and you cannot find the Problem </strong><br /> When working with the Python API, like all humans, you will have errors or code you want to debug; but how the heck do you debug it? Unfortunately, there are no out-of-the-box tools in Maya, but there are some good solutions available. Cyrille Fauvel from Autodesk has integrated a Maya Python debugger into the Eclipse IDE. The details are available on Autodesk.com, at the Maya Developer Center page. Dean Edmonds also from Autodesk has integrated the PDB debugger into the Script Editor within Maya by overriding the stdin and stout functions. Also, if you Google &ldquo;Python in Maya&rdquo; group you will see other solutions.</li> </ol> <ol start="4"> <li><strong>Knowing when and how to Use MScriptUtil Class</strong><br /> Many of the API methods in Maya require that one or more of their parameters be passed as pointers or references (return values can be pointers or references as well). Because Python does not have the concept of references or pointers, you will need the utility class called MScriptUtil for working with those pointers and references in Python. MScriptUtil bridges this gap between Python and its underlying C++ API. When you see the characters * or &amp; in the documentation for simple data types like integers and floats, think MScriptUtil!</li> </ol> <ol start="3"> <li><strong>The Reference Documentation is written for C++, but you are Using Python</strong><br /> If you do not know C++, at first glance the reference documentation will be very confusing!&nbsp; But don&rsquo;t worry; just put your eye blinders on to certain things when reading it. Because Python is a more simplified language than C++ (but none the less powerful), there are certain components in the documentation you can ignore. For example the class MString and MStringArray are not available in Python and instead you will work with strings as they are in native Python. Another example is that there is no MStatus class in Python and instead you will use standard Python error checking (try, except, catch). Try to think of this as having a mini translator going on in your brain, you see MStatus, so you just ignore it! </li> </ol> <ol start="2"> <li><strong>Trying to live in a Bubble and Teach Yourself Everything </strong><br /> There is no possible way to memorize or learn every single Maya API class, so don&rsquo;t be shy to use the resources available. As they say &ldquo;Be Resourceful&rdquo; and learn from others successes, mistakes and questions. Maya has been around for over ten years, and there is lots of API information out there (www.autodesk.com/developmaya). Also, you can check out the new book &ldquo;Maya Python for Games and Film: A Complete Reference for Maya Python and the Maya Python API&rdquo; by Adam Mechtley and Ryan Trowbridge.</li> </ol> <ol start="1"> <li><strong>Not Fully Grasping the Maya Architecture and How the Python API Leverages It</strong><br /> If you don&rsquo;t completely understanding the Maya architecture, command engine and the Dependency Graph, you will run into trouble as your tools get more complex. Take the time to learn these components as they are very different than any other animation product. Because of this complexity, it makes Maya more flexible and powerful than any other product. Check out the free Maya Python API webcast recording located here (www.autodesk.com/developmaya)</li> </ol>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c017616042632970c Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-07-02T00:25:00Ztag:api.typepad.com,2009:6a0163057a21c8970d017742cd1dfb970dAre you looking to rewrite some of our Maya default scripts?http://activitystrea.ms/schema/1.0/article2012-07-02T00:25:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p style="text-align: center;">First things first Happy Canada Day to all my fellow Canadians :)</p> <p><a href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017742cd132a970d-pi" style="display: inline;"><img alt="Images" border="0" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017742cd132a970d-800wi" style="margin-right: auto; margin-left: auto; display: block;" title="Images" /></a></p> <p>Are you looking to rewrite some of our Maya default scripts? In your environment, likely you will get to the point where you want to customize some of the MEL scripts that either builds the Maya UI or that create the functionality in Maya. To do this it means you will have to rewrite/change some of Maya’s default scripts.</p> <h2>Rewrite/Change a MEL script</h2> <p>Let’s examine all the ways to rewrite/change a MEL script with the help of Dean Edmonds our API Architect:</p> <h3>Option 1: Use the &#39;callbacks&#39; command</h3> <blockquote> <p><strong><em>PROS:</em></strong> Least intrusive.Easy to implement. Least chance of hidden surprises. Doesn&#39;t interfere with other plugi-ns&#39; overrides. Can be done and undone dynamically (e.g. when plugin loads and unloads).<br /> <br /> <strong><em>CONS: </em></strong>Will only work if the &#39;callbacks&#39; command happens to provide the override that you&#39;re looking for.</p> </blockquote> <h3>Option 2: Place your own version of the script in a directory which appears earlier in MAYA_SCRIPT_PATH than Maya&#39;s version</h3> <blockquote> <p><em><strong>PROS:</strong></em> Easy to implement. Few surprises. Can be done and undone dynamically with a bit of extra work. Works well in a small shop.</p> <p><em><strong>CONS:</strong></em> Can interfere with other plugins&#39; overrides of the same script. Can be difficult to manage as a 3rd-party plugin or in a large shop where you don&#39;t have control over paths.</p> </blockquote> <h3>Option 3: Source your own script which overrides only those procedures you&#39;re interested in</h3> <blockquote> <p>For example, let&#39;s say that you wanted to replace Maya&#39;s &#39;strip&#39; and &#39;startsWith&#39; commands, which are both implemented in MEL, with your own versions, whenever your plugin was loaded. First, you would create a script file, with a different name, which contained your versions of the strip() and startsWith() global procs:<br /> myOverrides.mel:<br /> <br /> global proc string strip(string $str)<br /> {<br /> &#0160;&#0160;&#0160; string $result = $str;<br /> &#0160;&#0160;&#0160; &lt;do your own stuff&gt;<br /> &#0160;&#0160;&#0160; return $result;<br /> }<br /> <br /> global proc int startsWith(string $s, string $prefix)<br /> {<br /> &#0160;&#0160;&#0160; int $result = false;<br /> &#0160;&#0160;&#0160; &lt;do your own stuff&gt;<br /> &#0160;&#0160;&#0160; return $result;<br /> }<br /> <br /> When your plugin loads it would do the following:<br /> source strip.mel; &#0160; &#0160; &#0160; &#0160;&#0160; &#0160; &#0160;&#0160;&#0160; // To make sure that Maya&#39;s versions are loaded.<br /> source startsWith.mel;<br /> source myOverrides.mel;&#0160;&#0160;&#0160; // To override Maya&#39;s versions with your own.<br /> <br /> When your plugin unloads, it should restore Maya&#39;s version:<br /> source strip.mel;<br /> source startsWith.mel;<br /> <br /> <em><strong>PROS:</strong></em> Your script doesn&#39;t need to override every procedure in the target script, only the ones you want to change. Doesn&#39;t require any control over paths, so works well in any environment. Can be done and undone dynamically. Less chance of interfering with other plugins&#39; overrides than option (b).<br /> <br /> <em><strong>CONS:</strong></em> You can only override global procs: if you need to override a local proc then you will need to override every proc which calls it to call your own instead. You cannot call local procs from Maya&#39;s version of the script: if you need to then you&#39;ll have to reproduce them in your own script. Some places in Maya explicitly source certain script files: if that happens to the one you&#39;re overriding then your override will be undone. There&#39;s still a possibility of interfering with other plugins&#39; overrides, though the chances are lessened.</p> </blockquote> <h2>Rewrite/Change a Python script</h2> <p>Okay that&#39;s great, but what about super cool Python :) Can we do the same as MEL? For Python there&#39;s really just one best way of doing it: replace methods dynamically at runTime.</p> <h3>Only Option: replace methods dynamically at runTime</h3> <blockquote> <p>Let&#39;s say that you want to add a hook into the listCommandPorts() method in CommandPort.py. You could do that using the following script at runTime:<br /> import maya.app.general.CommandPort as CommandPort<br /> <br /> originalMethod = CommandPort.listCommandPorts<br /> <br /> def myListPorts():<br /> &#0160;&#0160;&#0160; myHook()<br /> &#0160;&#0160;&#0160; return originalMethod()<br /> <br /> CommandPort.listCommandPorts = myListPorts<br /> <br /> Now whenever anyone in the current Maya process calls maya.app.general.CommandPort.listCommandPorts() they&#39;ll actually be calling your myListPorts() method.<br /> <br /> When you no longer need the hook, be sure to put the original method back:<br /> CommandPort.listCommandPorts = originalMethod<br /> <br /> One thing to keep in mind is that if you&#39;re replacing a non-static member method of a class, remember to include the &#39;self&#39; parameter at the start of the parameter list.<br /> <br /> <em><strong>PROS:</strong></em> Easy to implement. If you&#39;re just adding a hook and then calling through to the original method, it works very well with other plugins&#39; overrides since they just chain together.<br /> <br /> <em><strong>CONS</strong></em>: If your override can&#39;t call through to the original method then it can interfere other plugins&#39; overrides.</p> </blockquote> <p>Enjoy!</p> <p>Kristine</p> <p style="text-align: center;">First things first Happy Canada Day to all my fellow Canadians :)</p> <p><a href="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017742cd132a970d-pi" style="display: inline;"><img alt="Images" border="0" src="http://around-the-corner.typepad.com/.a/6a0163057a21c8970d017742cd132a970d-800wi" style="margin-right: auto; margin-left: auto; display: block;" title="Images" /></a></p> <p>Are you looking to rewrite some of our Maya default scripts? In your environment, likely you will get to the point where you want to customize some of the MEL scripts that either builds the Maya UI or that create the functionality in Maya. To do this it means you will have to rewrite/change some of Maya’s default scripts.</p> <h2>Rewrite/Change a MEL script</h2> <p>Let’s examine all the ways to rewrite/change a MEL script with the help of Dean Edmonds our API Architect:</p> <h3>Option 1: Use the &#39;callbacks&#39; command</h3> <blockquote> <p><strong><em>PROS:</em></strong> Least intrusive.Easy to implement. Least chance of hidden surprises. Doesn&#39;t interfere with other plugi-ns&#39; overrides. Can be done and undone dynamically (e.g. when plugin loads and unloads).<br /> <br /> <strong><em>CONS: </em></strong>Will only work if the &#39;callbacks&#39; command happens to provide the override that you&#39;re looking for.</p> </blockquote> <h3>Option 2: Place your own version of the script in a directory which appears earlier in MAYA_SCRIPT_PATH than Maya&#39;s version</h3> <blockquote> <p><em><strong>PROS:</strong></em> Easy to implement. Few surprises. Can be done and undone dynamically with a bit of extra work. Works well in a small shop.</p> <p><em><strong>CONS:</strong></em> Can interfere with other plugins&#39; overrides of the same script. Can be difficult to manage as a 3rd-party plugin or in a large shop where you don&#39;t have control over paths.</p> </blockquote> <h3>Option 3: Source your own script which overrides only those procedures you&#39;re interested in</h3> <blockquote> <p>For example, let&#39;s say that you wanted to replace Maya&#39;s &#39;strip&#39; and &#39;startsWith&#39; commands, which are both implemented in MEL, with your own versions, whenever your plugin was loaded. First, you would create a script file, with a different name, which contained your versions of the strip() and startsWith() global procs:<br /> myOverrides.mel:<br /> <br /> global proc string strip(string $str)<br /> {<br /> &#0160;&#0160;&#0160; string $result = $str;<br /> &#0160;&#0160;&#0160; &lt;do your own stuff&gt;<br /> &#0160;&#0160;&#0160; return $result;<br /> }<br /> <br /> global proc int startsWith(string $s, string $prefix)<br /> {<br /> &#0160;&#0160;&#0160; int $result = false;<br /> &#0160;&#0160;&#0160; &lt;do your own stuff&gt;<br /> &#0160;&#0160;&#0160; return $result;<br /> }<br /> <br /> When your plugin loads it would do the following:<br /> source strip.mel; &#0160; &#0160; &#0160; &#0160;&#0160; &#0160; &#0160;&#0160;&#0160; // To make sure that Maya&#39;s versions are loaded.<br /> source startsWith.mel;<br /> source myOverrides.mel;&#0160;&#0160;&#0160; // To override Maya&#39;s versions with your own.<br /> <br /> When your plugin unloads, it should restore Maya&#39;s version:<br /> source strip.mel;<br /> source startsWith.mel;<br /> <br /> <em><strong>PROS:</strong></em> Your script doesn&#39;t need to override every procedure in the target script, only the ones you want to change. Doesn&#39;t require any control over paths, so works well in any environment. Can be done and undone dynamically. Less chance of interfering with other plugins&#39; overrides than option (b).<br /> <br /> <em><strong>CONS:</strong></em> You can only override global procs: if you need to override a local proc then you will need to override every proc which calls it to call your own instead. You cannot call local procs from Maya&#39;s version of the script: if you need to then you&#39;ll have to reproduce them in your own script. Some places in Maya explicitly source certain script files: if that happens to the one you&#39;re overriding then your override will be undone. There&#39;s still a possibility of interfering with other plugins&#39; overrides, though the chances are lessened.</p> </blockquote> <h2>Rewrite/Change a Python script</h2> <p>Okay that&#39;s great, but what about super cool Python :) Can we do the same as MEL? For Python there&#39;s really just one best way of doing it: replace methods dynamically at runTime.</p> <h3>Only Option: replace methods dynamically at runTime</h3> <blockquote> <p>Let&#39;s say that you want to add a hook into the listCommandPorts() method in CommandPort.py. You could do that using the following script at runTime:<br /> import maya.app.general.CommandPort as CommandPort<br /> <br /> originalMethod = CommandPort.listCommandPorts<br /> <br /> def myListPorts():<br /> &#0160;&#0160;&#0160; myHook()<br /> &#0160;&#0160;&#0160; return originalMethod()<br /> <br /> CommandPort.listCommandPorts = myListPorts<br /> <br /> Now whenever anyone in the current Maya process calls maya.app.general.CommandPort.listCommandPorts() they&#39;ll actually be calling your myListPorts() method.<br /> <br /> When you no longer need the hook, be sure to put the original method back:<br /> CommandPort.listCommandPorts = originalMethod<br /> <br /> One thing to keep in mind is that if you&#39;re replacing a non-static member method of a class, remember to include the &#39;self&#39; parameter at the start of the parameter list.<br /> <br /> <em><strong>PROS:</strong></em> Easy to implement. If you&#39;re just adding a hook and then calling through to the original method, it works very well with other plugins&#39; overrides since they just chain together.<br /> <br /> <em><strong>CONS</strong></em>: If your override can&#39;t call through to the original method then it can interfere other plugins&#39; overrides.</p> </blockquote> <p>Enjoy!</p> <p>Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c017742d3d8b6970d Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-06-29T14:14:09Ztag:api.typepad.com,2009:6a0163057a21c8970d017742c53f1b970dUpdated Maya API Documentation Online and New Python API Learning Pathhttp://activitystrea.ms/schema/1.0/article2012-06-29T14:14:06Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<p>We have updated the Maya 2013 API Documentation, so please download the latest version here:</p> <p><a href="http://www.autodesk.com/me-sdk-docs">http://www.autodesk.com/me-sdk-docs</a></p> <p>Within the updated documentation there are two major additions which have been done by Martin Ashton are API documentations Guru:</p> <p>First, we have&#0160;&#0160;a brand new Maya Python Learning Path<br /><br /><a href="http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/files/GUID-856DDB26-93E7-493D-A1D4-60C4CBA38B9C.htm">http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/files/GUID-856DDB26-93E7-493D-A1D4-60C4CBA38B9C.htm</a></p> <p>Second,&#0160;a class taxonomy – all classes arranged according to subject/concept<br /><br /><a href="http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/cpp_ref/_maya.html">http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/cpp_ref/_maya.html</a></p> <p>Enjoy!</p> <p>Kristine</p> <p>We have updated the Maya 2013 API Documentation, so please download the latest version here:</p> <p><a href="http://www.autodesk.com/me-sdk-docs">http://www.autodesk.com/me-sdk-docs</a></p> <p>Within the updated documentation there are two major additions which have been done by Martin Ashton are API documentations Guru:</p> <p>First, we have&#0160;&#0160;a brand new Maya Python Learning Path<br /><br /><a href="http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/files/GUID-856DDB26-93E7-493D-A1D4-60C4CBA38B9C.htm">http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/files/GUID-856DDB26-93E7-493D-A1D4-60C4CBA38B9C.htm</a></p> <p>Second,&#0160;a class taxonomy – all classes arranged according to subject/concept<br /><br /><a href="http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/cpp_ref/_maya.html">http://docs.autodesk.com/MAYAUL/2013/ENU/Maya-API-Documentation/cpp_ref/_maya.html</a></p> <p>Enjoy!</p> <p>Kristine</p>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c017615b75dc8970c Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-06-22T09:26:01Ztag:api.typepad.com,2009:6a0163057a21c8970d0167677406e5970bWhat’s New in the FBX 2013 SDK?http://activitystrea.ms/schema/1.0/article2012-06-22T09:26:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<ul type="disc"> <li>The FBX SDK animation system has been completely redesigned.</li> <li>Take nodes, take node containers, current takes, and FCurves have all been replaced by animation stacks (FbxAnimStack), animation layers (FbxAnimLayer) animation curve nodes (FbxAnimCurveNode), and animation curves (FbxAnimCurve).</li> <li>The classes in the FBX SDK have all been renamed using the &quot;Fbx&quot; prefix, instead of &quot;KFbx&quot; or &quot;K&quot;. All structures have also been renamed with the same prefix, including global functions and enumerations. We did this to make the SDK simpler and more consistent.</li> <li>The FbxFile class has been exposed in fbxfile.h. This class will be a basic utility class used by the FBX SDK to open/read/write/close files.</li> <li>The FbxFileUtils class will expose all static functions related to file handling, such as remove, rename</li> <li>The FbxPathUtils class will expose all static functions related to file path handling, such as IsRelative, Clean</li> <li>Many FBX SDK functions which required file paths as inputs have been updated to support UTF-8. The parameter names were updated to reflect this change.</li> <li>Removed the KFbxMemoryAllocator class. Instead, use handler setter functions: FbxSetMallocHandler located in fbxalloc.h</li> <li>Removed all KFCurveFilter classes. Please use FbxAnimCurveFilter instead. It will be part of the animation refactoring that started in the 2011 version.</li> <li>The FbxLight class has been augmented to support area lights and barn doors.</li> <li>The FbxGeometryBase class has been augmented to support render options: PrimaryVisibility, CastShadow and ReceiveShadow.</li> <li>It will now be possible to retrieve the &quot;long&quot; version string of the FBX SDK via the function FbxManager::GetVersion(true). This will allow developers to get the version string of this library along with the name and the revision number.</li> <li>The FBX SDK will use secure versions of CRT calls on the Windows platform. It will no longer be necessary to disable these warnings when including the FBX SDK headers.</li> <li>Changed how objects are stored in the manager to help increase performance and reduce memory.</li> </ul> <ul type="disc"> <li>The FBX SDK animation system has been completely redesigned.</li> <li>Take nodes, take node containers, current takes, and FCurves have all been replaced by animation stacks (FbxAnimStack), animation layers (FbxAnimLayer) animation curve nodes (FbxAnimCurveNode), and animation curves (FbxAnimCurve).</li> <li>The classes in the FBX SDK have all been renamed using the &quot;Fbx&quot; prefix, instead of &quot;KFbx&quot; or &quot;K&quot;. All structures have also been renamed with the same prefix, including global functions and enumerations. We did this to make the SDK simpler and more consistent.</li> <li>The FbxFile class has been exposed in fbxfile.h. This class will be a basic utility class used by the FBX SDK to open/read/write/close files.</li> <li>The FbxFileUtils class will expose all static functions related to file handling, such as remove, rename</li> <li>The FbxPathUtils class will expose all static functions related to file path handling, such as IsRelative, Clean</li> <li>Many FBX SDK functions which required file paths as inputs have been updated to support UTF-8. The parameter names were updated to reflect this change.</li> <li>Removed the KFbxMemoryAllocator class. Instead, use handler setter functions: FbxSetMallocHandler located in fbxalloc.h</li> <li>Removed all KFCurveFilter classes. Please use FbxAnimCurveFilter instead. It will be part of the animation refactoring that started in the 2011 version.</li> <li>The FbxLight class has been augmented to support area lights and barn doors.</li> <li>The FbxGeometryBase class has been augmented to support render options: PrimaryVisibility, CastShadow and ReceiveShadow.</li> <li>It will now be possible to retrieve the &quot;long&quot; version string of the FBX SDK via the function FbxManager::GetVersion(true). This will allow developers to get the version string of this library along with the name and the revision number.</li> <li>The FBX SDK will use secure versions of CRT calls on the Windows platform. It will no longer be necessary to disable these warnings when including the FBX SDK headers.</li> <li>Changed how objects are stored in the manager to help increase performance and reduce memory.</li> </ul>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c0176159b3e42970c Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-06-18T08:21:03Ztag:api.typepad.com,2009:6a0163057a21c8970d017615699de5970cWhat’s New in the MotionBuilder 2013 SDK?http://activitystrea.ms/schema/1.0/article2012-06-18T08:21:00Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<ul type="disc"> <li>Programming Environment and Code Refactoring Changes</li> <ul type="circle"> <li>MotionBuilder and its distributed plug-ins are now compiled using Visual Studio 2010 (Service Pack 1).</li> <li>FBContainer has been renamed to FBVisualContainer for uniformity of cross-product naming schemes. </li> <li>const correctness improvements. </li> <li>Although not enforced in this release, we recommend that the &quot;H&quot; prefix in classes such as HFBPlug be removed and replaced by the pointer suffix &quot;*&quot;, for example: FBPlug*. This change is intended to facilitate the use of the documentation system in the near future. </li> <li>FBShader has been heavily refactored for performance.</li> </ul> <li>New Classes</li> <ul type="circle"> <li>FBSyncReference - Will allow the MotionBuilder application to sync its time with a device's time. For more information, consult the ordevicesync_device plugin. </li> <li>FBTimeCode - A timecode contains the time and frame information used to identify a specific moment in a timeline, often used in video and audio production. This class can help in the conversion of a point in time from one framerate domain to another. </li> <li>FBHUD, FBHUDElement - These classes represent the new Heads-Up Display (HUD) feature in MotionBuilder. A HUD will be connected to a camera, and appears as a 2D overlay. This overlay can be used to display information about the take: the current time and frame number </li> <li>FBFileMonitoringManager - This class can be used to help monitor operating system file events. By contrast, the event properties in FBApplication will only monitor events triggered within the MotionBuilder application.</li> <li>FBNamespace - This class has been exposed to help facilitate the use of namespaces among scene elements. Functions: FBFindModelByLabelName(), FBFbxOptions::NamespaceList, FBFbxOptions::SetNamespaceList(), FBFbxOptions::GetNamespaceList(), and the FBScene's namespace related functions (FBScene::NamespaceImport()) can filter, select, import and export scene elements using namespaces.</li> </ul> <li>New Methods and Added Functionality </li> <ul type="circle"> <li>FBAnimationNode::KeyCandidate(), FBPropertyAnimatable::KeyAt() - These functions &nbsp;provide the ability to key at a given time without moving time. </li> <li>FBSystem.ConfigPath, FBSystem.UserConfigPath, FBSystem.TempPath - These properties respectively will define MotionBuilder software&rsquo;s directory paths for config files, user config files, and temporary files. </li> <li>FBAudioClip - A substantial amount of functionality has been added to this class. Consult the header files and class documentation for more information. </li> <li>FBMenuManager - Functionality has been added to this class to help manipulate and remove MotionBuilder software&rsquo;s UI top menu bar. </li> <li>FBComponent::GetFullName() - Retrieves an object's unique name. </li> <li>FBStory, FBStoryFolder, FBStoryTrack - Added the capability to record stories on disk with properties: FBStory::RecordToDisk and FBStoryFolder::RecordClipPath. </li> <li>FBDevice::ModelBindingCreate, FBDevice::ModelBindingRootsList - These functions allow you to create a model binding from a device, or obtain a list of possible root models which can be bound to the device. </li> <li>FBModel - Exposed additional properties to facilitate custom rendering. Viewport dimensions can be set in the model, which will only be updated and valid during custom renderer callbacks (FBModel::CameraViewportX, FBModel::CameraViewportY, FBModel::CameraViewportWidth, FBModel::CameraViewportHeight). Motion blur properties have also been added: FBModel::MotionBlurIntensity, FBModel::UseMotionBlur, FBModel::UseRealTimeMotionBlur. </li> <li>FBModelNull, FBModelMarker - Overloaded several FBModel base class functions in these subclasses to help increase user customization. These functions are: FBModelMarker/FBModelNull::FbxStore(), FBModelMarker/FBModelNull::FbxRetrieve(), FBModelMarker/FBModelNull::FbxGetObject(), and FBModelMarker/FBModelNull::FbxGetObjectSubType(). </li> <li>FBMaterial - Custom material support, and added sample project (OpenRealitySDK/Samples/miscellaneous/material_template) </li> <li>FBRenderer - Added new functionality: FBRenderer::GetViewingCamera() to obtain the current camera, FBRenderer::InPicking() to determine if the renderer will be in the picking phase, and a variety of certain other functions and properties related to picking. </li> <li>FBAudioRenderOptions() - This class has been added to help specify audio rendering options, which can be passed as a parameter to FBApplication::AudioRender(). Consult the Scripts/Samples/Audio/AudioRendering.py sample for more details. </li> <li>FBEvaluateManager - Added functionality will allow for computationally intensive tasks to be registered and run as callbacks in a background thread (FBEvaluateManager::RegisterEvaluationGlobalFunction(), FBEvaluateManager::UnregisterEvaluationGlobalFunction())</li> </ul> <li>Misc and Optimizations</li> <ul type="circle"> <li>Optimized functions FBFindObjectByFullName() and FBDeleteObjectsByNames(). </li> <li>Optimized the merging of multiple files transaction workflow: FBMergeTransactionBegin(), FBMergeTransactionEnd().</li> </ul> </ul> <ul type="disc"> <li>Programming Environment and Code Refactoring Changes</li> <ul type="circle"> <li>MotionBuilder and its distributed plug-ins are now compiled using Visual Studio 2010 (Service Pack 1).</li> <li>FBContainer has been renamed to FBVisualContainer for uniformity of cross-product naming schemes. </li> <li>const correctness improvements. </li> <li>Although not enforced in this release, we recommend that the &quot;H&quot; prefix in classes such as HFBPlug be removed and replaced by the pointer suffix &quot;*&quot;, for example: FBPlug*. This change is intended to facilitate the use of the documentation system in the near future. </li> <li>FBShader has been heavily refactored for performance.</li> </ul> <li>New Classes</li> <ul type="circle"> <li>FBSyncReference - Will allow the MotionBuilder application to sync its time with a device's time. For more information, consult the ordevicesync_device plugin. </li> <li>FBTimeCode - A timecode contains the time and frame information used to identify a specific moment in a timeline, often used in video and audio production. This class can help in the conversion of a point in time from one framerate domain to another. </li> <li>FBHUD, FBHUDElement - These classes represent the new Heads-Up Display (HUD) feature in MotionBuilder. A HUD will be connected to a camera, and appears as a 2D overlay. This overlay can be used to display information about the take: the current time and frame number </li> <li>FBFileMonitoringManager - This class can be used to help monitor operating system file events. By contrast, the event properties in FBApplication will only monitor events triggered within the MotionBuilder application.</li> <li>FBNamespace - This class has been exposed to help facilitate the use of namespaces among scene elements. Functions: FBFindModelByLabelName(), FBFbxOptions::NamespaceList, FBFbxOptions::SetNamespaceList(), FBFbxOptions::GetNamespaceList(), and the FBScene's namespace related functions (FBScene::NamespaceImport()) can filter, select, import and export scene elements using namespaces.</li> </ul> <li>New Methods and Added Functionality </li> <ul type="circle"> <li>FBAnimationNode::KeyCandidate(), FBPropertyAnimatable::KeyAt() - These functions &nbsp;provide the ability to key at a given time without moving time. </li> <li>FBSystem.ConfigPath, FBSystem.UserConfigPath, FBSystem.TempPath - These properties respectively will define MotionBuilder software&rsquo;s directory paths for config files, user config files, and temporary files. </li> <li>FBAudioClip - A substantial amount of functionality has been added to this class. Consult the header files and class documentation for more information. </li> <li>FBMenuManager - Functionality has been added to this class to help manipulate and remove MotionBuilder software&rsquo;s UI top menu bar. </li> <li>FBComponent::GetFullName() - Retrieves an object's unique name. </li> <li>FBStory, FBStoryFolder, FBStoryTrack - Added the capability to record stories on disk with properties: FBStory::RecordToDisk and FBStoryFolder::RecordClipPath. </li> <li>FBDevice::ModelBindingCreate, FBDevice::ModelBindingRootsList - These functions allow you to create a model binding from a device, or obtain a list of possible root models which can be bound to the device. </li> <li>FBModel - Exposed additional properties to facilitate custom rendering. Viewport dimensions can be set in the model, which will only be updated and valid during custom renderer callbacks (FBModel::CameraViewportX, FBModel::CameraViewportY, FBModel::CameraViewportWidth, FBModel::CameraViewportHeight). Motion blur properties have also been added: FBModel::MotionBlurIntensity, FBModel::UseMotionBlur, FBModel::UseRealTimeMotionBlur. </li> <li>FBModelNull, FBModelMarker - Overloaded several FBModel base class functions in these subclasses to help increase user customization. These functions are: FBModelMarker/FBModelNull::FbxStore(), FBModelMarker/FBModelNull::FbxRetrieve(), FBModelMarker/FBModelNull::FbxGetObject(), and FBModelMarker/FBModelNull::FbxGetObjectSubType(). </li> <li>FBMaterial - Custom material support, and added sample project (OpenRealitySDK/Samples/miscellaneous/material_template) </li> <li>FBRenderer - Added new functionality: FBRenderer::GetViewingCamera() to obtain the current camera, FBRenderer::InPicking() to determine if the renderer will be in the picking phase, and a variety of certain other functions and properties related to picking. </li> <li>FBAudioRenderOptions() - This class has been added to help specify audio rendering options, which can be passed as a parameter to FBApplication::AudioRender(). Consult the Scripts/Samples/Audio/AudioRendering.py sample for more details. </li> <li>FBEvaluateManager - Added functionality will allow for computationally intensive tasks to be registered and run as callbacks in a background thread (FBEvaluateManager::RegisterEvaluationGlobalFunction(), FBEvaluateManager::UnregisterEvaluationGlobalFunction())</li> </ul> <li>Misc and Optimizations</li> <ul type="circle"> <li>Optimized functions FBFindObjectByFullName() and FBDeleteObjectsByNames(). </li> <li>Optimized the merging of multiple files transaction workflow: FBMergeTransactionBegin(), FBMergeTransactionEnd().</li> </ul> </ul>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collectiontag:api.typepad.com,2009:6e0120a5aeb1d3970c0163068034a1970d Kristine Middlemiss posted an entry http://activitystrea.ms/schema/1.0/post2012-06-13T11:14:53Ztag:api.typepad.com,2009:6a0163057a21c8970d01630680349f970dWhat’s New in the Maya 2013 API?http://activitystrea.ms/schema/1.0/article2012-06-13T11:14:52Ztag:api.typepad.com,2009:6p0120a5aeb1d3970cKristine Middlemisshttp://profile.typepad.com/6p0120a5aeb1d3970c<ul type="disc"> <li>The &ldquo;devkit/plug-ins&rdquo; folder has been reorganized so that the plug-in associated files are encapsulated under one folder and the plug-in project will be parented under a single parent solution file called &ldquo;Plug-ins.sln&rdquo;</li> <li>The module support for plug-in distribution has been improved so that you will be able to more easily create a distributable deployment of your plug-in. </li> <li>New attribute pattern API classes </li> <ul type="circle"> <li>MAttributePattern: class that will provide a pattern of attributes to be applied to nodes as dynamic attributes or to node classes as extension attributes.</li> <li>MAttributePatternArray: class that will provide methods for manipulating arrays of attribute patterns.</li> <li>MPxAttributeFactory: base class added for user-defined attribute pattern factories.</li> </ul> <li>New threaded device node classes added for creating threaded Maya device nodes</li> <ul type="circle"> <li>MPxThreadedDeviceNode: base class added for creating threaded Maya device nodes.</li> <li>MPxClientDeviceNode: extension of MPxThreadedDeviceNode, intended for creating Maya devices that act as clients.</li> <li>MCharBuffer (MPxThreadedDeviceNode.h): utility class added to deal with reference to a char* type.</li> </ul> <li>A group of new classes added under namespace MHWRender to work with index buffer and vertex buffer in Viewport 2.0 </li> <ul type="circle"> <li>MComponentDataIndexing: added class for storing index mapping when vertices are shared</li> <li>MComponentDataIndexingList: added class that defines a list of MComponentDataIndexing objects&nbsp;&nbsp;&nbsp; </li> <li>MHWGeometryUtilities: added a utility class for rendering geometry in Viewport 2.0, its wireframeColor() function will get the final wireframe color the draw can use.</li> <li>MGeometryExtractor: added base class for extracting renderable geometry, constructed an instance of this class to populate buffers with vertex and indexing data.</li> <li>MIndexBufferDescriptor (MHWGeometry.h): added class represents a description of an indexing scheme, indexing type, primitive type, primitive stride and component information.</li> <li>MIndexBufferDescriptorList (MHWGeometry.h): added a list of MIndexBufferDescriptor objects.</li> <li>MLightParameterInformation (MDrawContext.h): added a class for providing lighting information, which will allow for access to various per-light information accessible via the MDrawContext class in Viewport 2.0.</li> <li>MPxVertexBufferGenerator: added a base class for user defined vertex buffer generators.</li> </ul> <li>New classes added to provide callback hook into Maya software&rsquo;s drag-and-drop mechanism. </li> <ul type="circle"> <li>MExternalDropCallback: This class will be used to register callbacks to gain access to Maya software&rsquo;s drag-and-drop information during dropping an external object to Maya. You can replace or augment Maya software&rsquo;s drop behavior for external drag-and-drop operations. </li> <li>MExternalDropData: a class that represents data that a drag-and-drop operation carries if dragging from an external application and dropping onto Maya. It typically will arrive from a MExternalDropCallback callback method.</li> </ul> </ul> <ul type="disc"> <li>The &ldquo;devkit/plug-ins&rdquo; folder has been reorganized so that the plug-in associated files are encapsulated under one folder and the plug-in project will be parented under a single parent solution file called &ldquo;Plug-ins.sln&rdquo;</li> <li>The module support for plug-in distribution has been improved so that you will be able to more easily create a distributable deployment of your plug-in. </li> <li>New attribute pattern API classes </li> <ul type="circle"> <li>MAttributePattern: class that will provide a pattern of attributes to be applied to nodes as dynamic attributes or to node classes as extension attributes.</li> <li>MAttributePatternArray: class that will provide methods for manipulating arrays of attribute patterns.</li> <li>MPxAttributeFactory: base class added for user-defined attribute pattern factories.</li> </ul> <li>New threaded device node classes added for creating threaded Maya device nodes</li> <ul type="circle"> <li>MPxThreadedDeviceNode: base class added for creating threaded Maya device nodes.</li> <li>MPxClientDeviceNode: extension of MPxThreadedDeviceNode, intended for creating Maya devices that act as clients.</li> <li>MCharBuffer (MPxThreadedDeviceNode.h): utility class added to deal with reference to a char* type.</li> </ul> <li>A group of new classes added under namespace MHWRender to work with index buffer and vertex buffer in Viewport 2.0 </li> <ul type="circle"> <li>MComponentDataIndexing: added class for storing index mapping when vertices are shared</li> <li>MComponentDataIndexingList: added class that defines a list of MComponentDataIndexing objects&nbsp;&nbsp;&nbsp; </li> <li>MHWGeometryUtilities: added a utility class for rendering geometry in Viewport 2.0, its wireframeColor() function will get the final wireframe color the draw can use.</li> <li>MGeometryExtractor: added base class for extracting renderable geometry, constructed an instance of this class to populate buffers with vertex and indexing data.</li> <li>MIndexBufferDescriptor (MHWGeometry.h): added class represents a description of an indexing scheme, indexing type, primitive type, primitive stride and component information.</li> <li>MIndexBufferDescriptorList (MHWGeometry.h): added a list of MIndexBufferDescriptor objects.</li> <li>MLightParameterInformation (MDrawContext.h): added a class for providing lighting information, which will allow for access to various per-light information accessible via the MDrawContext class in Viewport 2.0.</li> <li>MPxVertexBufferGenerator: added a base class for user defined vertex buffer generators.</li> </ul> <li>New classes added to provide callback hook into Maya software&rsquo;s drag-and-drop mechanism. </li> <ul type="circle"> <li>MExternalDropCallback: This class will be used to register callbacks to gain access to Maya software&rsquo;s drag-and-drop information during dropping an external object to Maya. You can replace or augment Maya software&rsquo;s drop behavior for external drag-and-drop operations. </li> <li>MExternalDropData: a class that represents data that a drag-and-drop operation carries if dragging from an external application and dropping onto Maya. It typically will arrive from a MExternalDropCallback callback method.</li> </ul> </ul>tag:api.typepad.com,2009:6a0163057a21c8970d0163057a224d970dAround the Cornerhttp://activitystrea.ms/schema/1.0/collection