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

<channel>
	<title>Nathan Horne - Technical Artist</title>
	<atom:link href="http://nathanhorne.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://nathanhorne.com</link>
	<description></description>
	<lastBuildDate>Sat, 26 Jun 2010 04:04:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Maya GUI excepthook</title>
		<link>http://nathanhorne.com/?p=245</link>
		<comments>http://nathanhorne.com/?p=245#comments</comments>
		<pubDate>Fri, 25 Jun 2010 17:20:11 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Exception]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=245</guid>
		<description><![CDATA[Autodesk passes all exceptions thrown in the command engine when in GUI mode to maya.utils._guiExceptHook, rather than doing it the way that Python does it natively through sys.excepthook.  Here&#8217;s a simple workaround if you want to modify that behavior at run-time.
You can just overload the function of the imported module like so:
import sys
import maya.cmds [...]]]></description>
			<content:encoded><![CDATA[<p>Autodesk passes all exceptions thrown in the command engine when in GUI mode to maya.utils._guiExceptHook, rather than doing it the way that Python does it natively through sys.excepthook.  Here&#8217;s a simple workaround if you want to modify that behavior at run-time.</p>
<p>You can just overload the function of the imported module like so:</p>
<pre class="brush: python;">import sys
import maya.cmds as cmds

utils = sys.modules['maya.utils']
def excepthook(tb_type, exc_object, tb, detail=2):
	print '='*40
	print utils.formatGuiException(tb_type, exc_object, tb, detail)
	cmds.ScriptEditor()
	print '='*40

	import pdb
	pdb.post_mortem(tb)
	return utils.formatGuiException(tb_type, exc_object, tb, detail)

utils._guiExceptHook = excepthook</pre>
<p>Or, if you want to get the normal behavior back, you can do this:</p>
<pre class="brush: python;">import sys
import maya.cmds as cmds

utils = sys.modules['maya.utils']
def excepthook(tb_type, exc_object, tb, detail=2):
	if sys.excepthook != sys.__excepthook__:
		sys.excepthook(tb_type, exc_object, tb)
	return utils.formatGuiException(tb_type, exc_object, tb, detail)

utils._guiExceptHook = excepthook</pre>
<p>Now, when an exception is fired, it will first run your custom excepthook (if modified, if not it will just skip it).</p>
<p>Note: your function must return a string, and that string will be passed by the Maya command engine to MGlobal.displayError()</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=245</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maya python selectFromScreen</title>
		<link>http://nathanhorne.com/?p=233</link>
		<comments>http://nathanhorne.com/?p=233#comments</comments>
		<pubDate>Mon, 14 Jun 2010 22:39:12 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[API]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=233</guid>
		<description><![CDATA[Something I whipped up to get the selection from the screen using the Maya API in python, just returns the selection as a list of dag path&#8217;s.
Maya&#8217;s API selecFromScreen is great, except for the fact that for what I needed, I only wanted a list of object from the screen, not to actually select them.
import [...]]]></description>
			<content:encoded><![CDATA[<p>Something I whipped up to get the selection from the screen using the Maya API in python, just returns the selection as a list of dag path&#8217;s.</p>
<p>Maya&#8217;s API selecFromScreen is great, except for the fact that for what I needed, I only wanted a list of object from the screen, not to actually select them.</p>
<pre class="brush: python;">import maya.OpenMaya as api

def selectFromScreenApi(x, y, x_rect=None, y_rect=None):
	#get current selection
	sel = api.MSelectionList()
	api.MGlobal.getActiveSelectionList(sel)

	#select from screen
	args = [x, y]
	if x_rect!=None and y_rect!=None:
		api.MGlobal.selectFromScreen(x, y, x_rect, y_rect, api.MGlobal.kReplaceList)
	else:
		api.MGlobal.selectFromScreen(x, y, api.MGlobal.kReplaceList)
	objects = api.MSelectionList()
	api.MGlobal.getActiveSelectionList(objects)

	#restore selection
	api.MGlobal.setActiveSelectionList(sel, api.MGlobal.kReplaceList)

	#return the objects as strings
	fromScreen = []
	objects.getSelectionStrings(fromScreen)
	return fromScreen

print selectFromScreenApi(0, 0)
print selectFromScreenApi(0, 0, 4096, 4096)
</pre>
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=233</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Compiled PyQt 4.7.3 and sip x86</title>
		<link>http://nathanhorne.com/?p=229</link>
		<comments>http://nathanhorne.com/?p=229#comments</comments>
		<pubDate>Mon, 14 Jun 2010 06:33:15 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[PyQt]]></category>
		<category><![CDATA[SIP]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=229</guid>
		<description><![CDATA[Compiled against Qt 4.5.3 (2009.04) and python 2.6.4 (Both the same as Maya 2011):
PyQt-Py2.6-gpl-4.7.3-1_QT_MAYA_x86.exe
sip.pyd
]]></description>
			<content:encoded><![CDATA[<p>Compiled against Qt 4.5.3 (2009.04) and python 2.6.4 (Both the same as Maya 2011):</p>
<p><a href="http://dl.dropbox.com/u/1633130/PyQt%20x86/PyQt-Py2.6-gpl-4.7.3-1_QT_MAYA_x86.exe">PyQt-Py2.6-gpl-4.7.3-1_QT_MAYA_x86.exe</a></p>
<p><a href="http://dl.dropbox.com/u/1633130/PyQt%20x86/sip.pyd">sip.pyd</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=229</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Compiled Versions of PyQt4 x64</title>
		<link>http://nathanhorne.com/?p=204</link>
		<comments>http://nathanhorne.com/?p=204#comments</comments>
		<pubDate>Thu, 27 May 2010 18:14:31 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[PyQt]]></category>
		<category><![CDATA[SIP]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=204</guid>
		<description><![CDATA[After getting fed up with using someone else&#8217;s out of date versions, I decided to compile my own Qt, SIP, and PyQt for x64. I managed to get it all working and figured I could share it up, so here&#8217;s a link to the installers, as well as the latest version of sip.pyd which you [...]]]></description>
			<content:encoded><![CDATA[<p>After getting fed up with using someone else&#8217;s out of date versions, I decided to compile my own Qt, SIP, and PyQt for x64. I managed to get it all working and figured I could share it up, so here&#8217;s a link to the installers, as well as the latest version of sip.pyd which you will need.</p>
<p><a href="http://dl.dropbox.com/u/1633130/PyQt-Py2.6-gpl-4.7.3-1_QT_MAYA.exe">PyQt-Py2.6-gpl-4.7.3-1_QT_MAYA.exe</a><br />
<a href="http://dl.dropbox.com/u/1633130/PyQt-Py2.6-gpl-4.7.3-1.exe">PyQt-Py2.6-gpl-4.7.3-1.exe</a><br />
<a href="http://dl.dropbox.com/u/1633130/sip.pyd">sip.pyd</a></p>
<p>Both are the latest PyQt4 4.7.3-1, however they are compiled against different versions of QT.<br />
PyQt-Py2.6-gpl-4.7.3-1_QT_MAYA.exe is compiled against Qt 4.5.3 (2009.04) which Maya 2011 uses, the other is compiled against the latest Qt 4.6.2 (2010.02.1).</p>
<p>Also, please note that I did not include any components that do not come standard with the Qt SDK such as QScintilla.</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=204</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Python Rivet script</title>
		<link>http://nathanhorne.com/?p=196</link>
		<comments>http://nathanhorne.com/?p=196#comments</comments>
		<pubDate>Wed, 05 May 2010 23:32:07 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=196</guid>
		<description><![CDATA[I&#8217;ve had to use this at work recently, andIi decided to revamp an old mel script I had been using before.  I figured I would share it up for others to use.
Right click, save-as.
Public SVN repository web view
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had to use this at work recently, andIi decided to revamp an old mel script I had been using before.  I figured I would share it up for others to use.</p>
<p><a href="http://temujin.dnsalias.com/svn/public/nph_rivet.py">Right click, save-as.</a></p>
<p><a href="http://temujin.dnsalias.com/svn/public/">Public SVN repository web view</a></p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=196</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PyQt and Maya 2011</title>
		<link>http://nathanhorne.com/?p=183</link>
		<comments>http://nathanhorne.com/?p=183#comments</comments>
		<pubDate>Wed, 21 Apr 2010 18:04:32 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[PyQt]]></category>
		<category><![CDATA[SIP]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=183</guid>
		<description><![CDATA[Re-posting some information here that I had posted on TD club:

import maya.OpenMayaUI as mui
import PyQt4.QtCore as QtCore
import PyQt4.QtGui as QtGui
import sip

def getMayaWindow():
    #Get the maya main window as a QMainWindow instance
    ptr = mui.MQtUtil.mainWindow()
    return sip.wrapinstance(long(ptr), QtCore.QObject)

class MayaSubWindow(QtGui.QMainWindow):
    'My custom window, which i [...]]]></description>
			<content:encoded><![CDATA[<p>Re-posting some information here that I had posted on TD club:</p>
<pre class="brush: python;">
import maya.OpenMayaUI as mui
import PyQt4.QtCore as QtCore
import PyQt4.QtGui as QtGui
import sip

def getMayaWindow():
    #Get the maya main window as a QMainWindow instance
    ptr = mui.MQtUtil.mainWindow()
    return sip.wrapinstance(long(ptr), QtCore.QObject)

class MayaSubWindow(QtGui.QMainWindow):
    'My custom window, which i want to parent to the maya main window'
    def __init__(self, parent=getMayaWindow()):
        #Init my main window, and pass in the maya main window as it's parent
        QtGui.QMainWindow.__init__(self, parent)

#Show my window
myWindow = MayaSubWindow()
myWindow.show()</pre>
<p>Here&#8217;s a quick little bit of code showing how to create a custom GUI class using pyqt (Almost all the pyqt examples use this over using some form of .ui file, because it allows for much more control). You can also use it in combination with ui files thanks to pyqt&#8217;s uic module.</p>
<p>QT does not require objects to have &#8220;names&#8221;, but if you ever want to find your pyqt objects using MQtUil.findControl then you need to assign it a name using OBJECT.setObjectName(&#8220;AwesomeWindow&#8221;). In the above example, in the MayaSubWindow.__init__ function you would call self.setObjectName(&#8220;AwesomeWindow&#8221;).<br style="font-size: 1em; position: static !important;" /><br style="font-size: 1em; position: static !important;" />Also, since qt does not require names, it also does not require that control names be unique, so it&#8217;s completely possible to use findControl and get the &#8220;wrong&#8221; object. So you may want to ensure that the name you are using is unique if you want to use it to find that object again later. (Also, you can skip the whole findControl step by just using instance variables to keep track of all your controls, like what the pyqt examples use)</p>
<p>Here&#8217;s a pyqt example using uic to load in a ui file (Rather than maya&#8217;s new loadUi command, which wont give you all your pyqt objects.</p>
<pre class="brush: python;">
import os
import sip

import maya.cmds as cmds
import maya.OpenMayaUI as mui

from PyQt4 import QtGui, QtCore, uic

def getMayaWindow():
	'Get the maya main window as a QMainWindow instance'
	ptr = mui.MQtUtil.mainWindow()
	return sip.wrapinstance(long(ptr), QtCore.QObject)

#Get the absolute path to my ui file
uiFile = os.path.join(cmds.internalVar(upd=True), 'ui', 'demo.ui')
print 'Loading ui file:', os.path.normpath(uiFile)

#Load the ui file, and create my class
form_class, base_class = uic.loadUiType(uiFile)
class Window(base_class, form_class):
	def __init__(self, parent=getMayaWindow()):
		'''A custom window with a demo set of ui widgets'''
		#init our ui using the MayaWindow as parent
		super(base_class, self).__init__(parent)
		#uic adds a function to our class called setupUi, calling this creates all the widgets from the .ui file
		self.setupUi(self)
		self.setObjectName('myWindow')
		self.setWindowTitle(&quot;My Qt Demo Window&quot;)

def main():
	global myWindow
	myWindow = Window()
	myWindow.show()</pre>
<p><a href="http://nathanh.pastebin.com/download.php?i=mEEp8sxq">Designer .UI file</a></p>
<pre><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; white-space: normal; font-size: 13.2px;">The python code will look for the ui file in maya2011\prefs\ui\demo.ui. It will print a message with the absolute path when running.</span></pre>
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=183</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Timer threads</title>
		<link>http://nathanhorne.com/?p=116</link>
		<comments>http://nathanhorne.com/?p=116#comments</comments>
		<pubDate>Tue, 18 Aug 2009 17:41:47 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=116</guid>
		<description><![CDATA[Timers have all sorts of uses, and unfortunately up until 8.5 Maya had no good way of checking a timer, and running a background event.
Previously you could check system time at certain events with a scriptJob, like selectionChanged, but it tends to slow Maya down right when the user was trying to interact.. so in [...]]]></description>
			<content:encoded><![CDATA[<p>Timers have all sorts of uses, and unfortunately up until 8.5 Maya had no good way of checking a timer, and running a background event.</p>
<p>Previously you could check system time at certain events with a scriptJob, like selectionChanged, but it tends to slow Maya down right when the user was trying to interact.. so in a production environment that wasn&#8217;t a viable solution (usually scriptJobs aren&#8217;t, as nifty as they are).</p>
<p>Now, with the flexibility of python in Maya, and python&#8217;s ability to create threads, it&#8217;s quite simple to create a basic Timer class.</p>
<p>Note: I updated it to use threading.Event().wait() instead of a time.sleep() loop, and now I directly subclass threading.Thread.</p>
<pre class="brush: python;">
'''
Usage:
def timerTest():
	print 'Hello World!'

#create and start a timer
timer = Timer(30, timerTest, repeat=True)
timer.start()

#To stop the timer
timer.stop()
'''

import threading

try:
	from maya.utils import executeInMainThreadWithResult
except:
	executeInMainThreadWithResult = None

class Timer(threading.Thread):
	def __init__(self, interval, function, args=[], kwargs={}, repeat=True):
		self.interval = interval
		self.function = function
		self.repeat = repeat
		self.args = args
		self.kwargs = kwargs
		self.event = threading.Event()
		threading.Thread.__init__(self)

	def run(self):
		def _mainLoop():
			self.event.wait(self.interval)
			if not self.event.isSet():
				if executeInMainThreadWithResult:
					executeInMainThreadWithResult(self.function, *self.args, **self.kwargs)
				else:
					self.function(*self.args, **self.kwargs)

		if self.repeat:
			while not self.event.isSet():
				_mainLoop()
		else:
			_mainLoop()
			self.stop()

	def start(self):
		self.event.clear()
		threading.Thread.start(self)

	def stop(self):
		self.event.set()
		threading.Thread.__init__(self)</pre>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">&#8221;&#8217;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">Usage:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">def timerTest():</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>print &#8216;Hello World!&#8217;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">#create and start a timer</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer = Timer(30, timerTest, repeat=True)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer.start()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">#To stop the timer</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">timer.stop()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">&#8221;&#8217;</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">import threading</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">try:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>from maya.utils import executeInMainThreadWithResult</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">except:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>executeInMainThreadWithResult = None</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;">class Timer(threading.Thread):</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>def __init__(self, interval, function, args=[], kwargs={}, repeat=True):</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.interval = interval</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.function = function</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.repeat = repeat</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.args = args</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.kwargs = kwargs</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.event = threading.Event()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>threading.Thread.__init__(self)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>def run(self):</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>def _mainLoop():</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.event.wait(self.interval)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if not self.event.isSet():</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if executeInMainThreadWithResult:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>executeInMainThreadWithResult(self.function, *self.args, **self.kwargs)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>else:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.function(*self.args, **self.kwargs)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>if self.repeat:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>while not self.event.isSet():</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>_mainLoop()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>else:</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>_mainLoop()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.stop()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span></div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>def start(self):</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.event.clear()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>threading.Thread.start(self)</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>def stop(self):</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>self.event.set()</div>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow-x: hidden; overflow-y: hidden;"><span style="white-space: pre;"> </span>threading.Thread.__init__(self)</div>
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=116</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL logging from Maya</title>
		<link>http://nathanhorne.com/?p=92</link>
		<comments>http://nathanhorne.com/?p=92#comments</comments>
		<pubDate>Sat, 15 Aug 2009 17:41:42 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=92</guid>
		<description><![CDATA[I was inspired by a post on tech-artists by Adam Pletcher over at Volition, he talked about using SQL to track usage stats for tools, and startup time for 3dsmax.
Getting the data:
I started with a simple database,  just tracking the tool name, the username, and the date/time. But there is room to expand that information later [...]]]></description>
			<content:encoded><![CDATA[<p style="text-align: left;">I was inspired by a <a href="http://tech-artists.org/forum/showpost.php?p=3391&amp;postcount=27" target="_blank">post on tech-artists</a> by Adam Pletcher over at Volition, he talked about using SQL to track usage stats for tools, and startup time for 3dsmax.</p>
<p style="text-align: left;"><strong>Getting the data:</strong></p>
<p style="text-align: left;">I started with a simple database,  just tracking the tool name, the username, and the date/time. But there is room to expand that information later (I want to track arguments, and time taken per tool).</p>
<p style="text-align: left;">There&#8217;s a problem right away: accessing a remote database on every function call (that I want to track) is SLOW, to work around this I dump the data to a local temp file (I used csv), and use a timer in a separate thread to upload every N seconds (on my machine I do every 10 seconds, for the artist&#8217;s I&#8217;m still tweaking, but somewhere around 2-5 minutes seems to work well). The actual database access usually takes .1 to .5 of a second, so it&#8217;s not terrible. I also have it set to run with utils.executeDeferred(), so it goes unnoticed for me, even on my 10 second interval.</p>
<p style="text-align: left;">Sooo&#8230; I have a bunch of cool data in a table, now what?</p>
<p style="text-align: left;">
<p style="text-align: left;"><strong>CHARTS! <img src='http://nathanhorne.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </strong></p>
<p style="text-align: left;"><strong> </strong></p>
<div id="attachment_111" class="wp-caption alignnone" style="width: 490px"><a href="http://nathanhorne.com/wp-content/uploads/2009/08/output1.png"><img class="size-full wp-image-111 " title="Function usage breakdown" src="http://nathanhorne.com/wp-content/uploads/2009/08/output1.png" alt="It even has alpha! :)" width="480" height="320" /></a><p class="wp-caption-text">It even has alpha! <img src='http://nathanhorne.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p></div>
<p style="text-align: left;">I used pycha and pycairo to create charts from the database, had to track down some missing dll&#8217;s to get it working, but not too bad. So far the most useful chart is function usage by user (given a  function, % that each person uses it), it helps me to spot tools that aren&#8217;t being used by certain users, which will allow me to train them on the new tool. This is good because if they never use it, they probably don&#8217;t know it exists.. <img src='http://nathanhorne.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p style="text-align: left;"><strong>Where to go from here:</strong></p>
<p style="text-align: left;">Break functions down by how long they take to execute, it should show me where most of our processor time is going as far as tools are concerned, so once I turn on function timing, that&#8217;s an immediate goal.</p>
<p style="text-align: left;">
<p style="text-align: left;">
<p style="text-align: left;">
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=92</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Assigning to __main__ in Maya</title>
		<link>http://nathanhorne.com/?p=71</link>
		<comments>http://nathanhorne.com/?p=71#comments</comments>
		<pubDate>Wed, 12 Aug 2009 05:49:08 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Maya]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=71</guid>
		<description><![CDATA[A cool feature of Maya&#8217;s python is that it runs as an interactive session, and that lets you do this neat trick from any imported module
you can add objects to the __main__ namespace (The script editor&#8217;s interactive prompt), this is also where python will search when you use the MEL command python();
from some python file:

#import [...]]]></description>
			<content:encoded><![CDATA[<p>A cool feature of Maya&#8217;s python is that it runs as an interactive session, and that lets you do this neat trick from any imported module</p>
<p>you can add objects to the __main__ namespace (The script editor&#8217;s interactive prompt), this is also where python will search when you use the MEL command python();</p>
<p>from some python file:</p>
<pre class="brush: python;">
#import the interactive main module
import __main__

def someCommand():
'''This is a pretty basic function...'''
print 'someCommand called!'

#now assign it to an attribute in __main__
__main__.someCommand = someCommand
</pre>
<pre class="brush: plain;">
python(&quot;someCommand()&quot;);
// someCommand called!
</pre>
<p>This can also be used as a way to create global variables across multiple modules, as it is always present so long as Maya is open (although any attributes you define may not be, so check first <img src='http://nathanhorne.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> )</p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=71</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Welcome to the new NathanHorne.com!</title>
		<link>http://nathanhorne.com/?p=67</link>
		<comments>http://nathanhorne.com/?p=67#comments</comments>
		<pubDate>Wed, 12 Aug 2009 05:33:23 +0000</pubDate>
		<dc:creator>Nathan</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://nathanhorne.com/?p=67</guid>
		<description><![CDATA[I have everything set up the way I want it now   I&#8217;m running wordpress and a home server with Apache + subversion + Trac. So I can keep track of all my personal projects and files on the go. As a bonus, anyone who visits can yell at me for slacking on my [...]]]></description>
			<content:encoded><![CDATA[<p>I have everything set up the way I want it now <img src='http://nathanhorne.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  I&#8217;m running wordpress and a home server with Apache + subversion + Trac. So I can keep track of all my personal projects and files on the go. As a bonus, anyone who visits can yell at me for slacking on my personal work! <img src='http://nathanhorne.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://nathanhorne.com/?feed=rss2&amp;p=67</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- www.000webhost.com Analytics Code -->
<script type="text/javascript" src="http://analytics.hosting24.com/count.php"></script>
<noscript><a href="http://www.hosting24.com/"><img src="http://analytics.hosting24.com/count.php" alt="web hosting" /></a></noscript>
<!-- End Of Analytics Code -->
